<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><div id="myscoll"></div><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>SpringBoot | XiaoFei🥝</title><meta name="keywords" content="SpringBoot"><meta name="author" content="XiaoFei🥝"><meta name="copyright" content="XiaoFei🥝"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="ffffff"><meta name="description" content="SpringBoot">
<meta property="og:type" content="article">
<meta property="og:title" content="SpringBoot">
<meta property="og:url" content="https://www.naste.top:1024/posts/1864766114.html">
<meta property="og:site_name" content="XiaoFei🥝">
<meta property="og:description" content="SpringBoot">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://www.naste.top:9000/webp/1515952743771.webp">
<meta property="article:published_time" content="2022-06-15T10:01:02.000Z">
<meta property="article:modified_time" content="2024-04-26T09:52:18.155Z">
<meta property="article:author" content="XiaoFei🥝">
<meta property="article:tag" content="Java">
<meta property="article:tag" content="SpringBoot">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://www.naste.top:9000/webp/1515952743771.webp"><link rel="shortcut icon" href="/"><link rel="canonical" href="https://www.naste.top:1024/posts/1864766114"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.staticfile.org/fancyapps-ui/4.0.31/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.json","preload":true,"languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: undefined,
  noticeOutdate: {"limitDay":365,"position":"top","messagePrev":"It has been","messageNext":"days since the last update, the content of the article may be outdated."},
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":230},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: true,
    post: true
  },
  runtime: '',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    justifiedGallery: {
      js: 'https://cdnjs.cloudflare.com/ajax/libs/flickr-justified-gallery/2.1.2/fjGallery.min.js',
      css: 'https://cdnjs.cloudflare.com/ajax/libs/flickr-justified-gallery/2.1.2/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'SpringBoot',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2024-04-26 17:52:18'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', 'ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          const now = new Date()
          const hour = now.getHours()
          const isNight = hour <= 6 || hour >= 18
          if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
          else if (t === 'light') activateLightMode()
          else activateDarkMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><link rel="stylesheet" href="https://cdn1.tianli0.top/npm/element-ui@2.15.6/packages/theme-chalk/lib/index.css"><style id="themeColor"></style><style id="rightSide"></style><style id="transPercent"></style><style id="blurNum"></style><style id="settingStyle"></style><span id="fps"></span><style id="defineBg"></style><style id="menu_shadow"></style><svg aria-hidden="true" style="position:absolute; overflow:hidden; width:0; height:0"><symbol id="icon-sun" viewBox="0 0 1024 1024"><path d="M960 512l-128 128v192h-192l-128 128-128-128H192v-192l-128-128 128-128V192h192l128-128 128 128h192v192z" fill="#FFD878" p-id="8420"></path><path d="M736 512a224 224 0 1 0-448 0 224 224 0 1 0 448 0z" fill="#FFE4A9" p-id="8421"></path><path d="M512 109.248L626.752 224H800v173.248L914.752 512 800 626.752V800h-173.248L512 914.752 397.248 800H224v-173.248L109.248 512 224 397.248V224h173.248L512 109.248M512 64l-128 128H192v192l-128 128 128 128v192h192l128 128 128-128h192v-192l128-128-128-128V192h-192l-128-128z" fill="#4D5152" p-id="8422"></path><path d="M512 320c105.888 0 192 86.112 192 192s-86.112 192-192 192-192-86.112-192-192 86.112-192 192-192m0-32a224 224 0 1 0 0 448 224 224 0 0 0 0-448z" fill="#4D5152" p-id="8423"></path></symbol><symbol id="icon-moon" viewBox="0 0 1024 1024"><path d="M611.370667 167.082667a445.013333 445.013333 0 0 1-38.4 161.834666 477.824 477.824 0 0 1-244.736 244.394667 445.141333 445.141333 0 0 1-161.109334 38.058667 85.077333 85.077333 0 0 0-65.066666 135.722666A462.08 462.08 0 1 0 747.093333 102.058667a85.077333 85.077333 0 0 0-135.722666 65.024z" fill="#FFB531" p-id="11345"></path><path d="M329.728 274.133333l35.157333-35.157333a21.333333 21.333333 0 1 0-30.165333-30.165333l-35.157333 35.157333-35.114667-35.157333a21.333333 21.333333 0 0 0-30.165333 30.165333l35.114666 35.157333-35.114666 35.157334a21.333333 21.333333 0 1 0 30.165333 30.165333l35.114667-35.157333 35.157333 35.157333a21.333333 21.333333 0 1 0 30.165333-30.165333z" fill="#030835" p-id="11346"></path></symbol></svg><!-- hexo injector head_end start --><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiperstyle.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/assets/font-awesome-animation.min.css" media="defer" onload="this.media='all'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/tag_plugins.css" media="defer" onload="this.media='all'"><script src="https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/assets/carousel-touch.js"></script><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/animate.min.css" media="print" onload="this.media='screen'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-filter-gitcalendar/lib/gitcalendar.css" media="print" onload="this.media='all'"><!-- hexo injector head_end end --><meta name="generator" content="Hexo 6.3.0"><link rel="alternate" href="/atom.xml" title="XiaoFei🥝" type="application/atom+xml">
</head><body><div id="loading-box" onclick="document.getElementById(&quot;loading-box&quot;).classList.add(&quot;loaded&quot;)"><div class="loading-bg"><div class="loading-img"></div><div class="loading-image-dot"></div></div></div><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="https://www.naste.top:9000/images/cat.jpg" onerror="onerror=null;src='/assets/r1.jpg'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">149</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">99</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">46</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-home"></use></svg><span class="menu_word" style="font-size:17px"> 首页</span></a></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon--article"></use></svg><span class="menu_word" style="font-size:17px"> 文章</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-guidang1">                   </use></svg><span class="menu_word" style="font-size:17px"> 归档</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-sekuaibiaoqian">                   </use></svg><span class="menu_word" style="font-size:17px"> 标签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-fenlei">                   </use></svg><span class="menu_word" style="font-size:17px"> 分类</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-pinweishenghuo"></use></svg><span class="menu_word" style="font-size:17px"> 休闲</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/life/music/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-yinle">                   </use></svg><span class="menu_word" style="font-size:17px"> 八音盒</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/life/movies/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-dianying1">                   </use></svg><span class="menu_word" style="font-size:17px"> 影院</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/life/games/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-youxishoubing">                   </use></svg><span class="menu_word" style="font-size:17px"> 游戏</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-xiangzi"></use></svg><span class="menu_word" style="font-size:17px"> 八宝箱</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/box/gallery/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-tubiaozhizuomoban">                   </use></svg><span class="menu_word" style="font-size:17px"> 画廊</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/box/animation/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-nvwumao">                   </use></svg><span class="menu_word" style="font-size:17px"> 动画</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/box/nav/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-zhifengche">                   </use></svg><span class="menu_word" style="font-size:17px"> 网址导航</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-shejiaoxinxi"></use></svg><span class="menu_word" style="font-size:17px"> 社交</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/social/fcircle/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-pengyouquan">                   </use></svg><span class="menu_word" style="font-size:17px"> 朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/comments/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-liuyan">                   </use></svg><span class="menu_word" style="font-size:17px"> 留言板</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/social/link/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-lianjie">                   </use></svg><span class="menu_word" style="font-size:17px"> 友人帐</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-wangye"></use></svg><span class="menu_word" style="font-size:17px"> 网站</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/site/census/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon--tongjibiao">                   </use></svg><span class="menu_word" style="font-size:17px"> 网站统计</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/site/echarts/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-shujutongji1">                   </use></svg><span class="menu_word" style="font-size:17px"> 文章统计</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/site/time/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-xianxingshalou">                   </use></svg><span class="menu_word" style="font-size:17px"> 旧时光</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-maoliang"></use></svg><span class="menu_word" style="font-size:17px"> 个人</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/personal/bb/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-qunliaotian">                   </use></svg><span class="menu_word" style="font-size:17px"> 唠叨</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/personal/love/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-love-sign">                   </use></svg><span class="menu_word" style="font-size:17px"> 恋爱小屋</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/personal/about/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-paperplane">                   </use></svg><span class="menu_word" style="font-size:17px"> 关于</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/encryption/%E6%9C%BA%E5%9C%BA/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-paperplane">                   </use></svg><span class="menu_word" style="font-size:17px"> 机场</span></a></li></ul></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">XiaoFei🥝</a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-home"></use></svg><span class="menu_word" style="font-size:17px"> 首页</span></a></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon--article"></use></svg><span class="menu_word" style="font-size:17px"> 文章</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-guidang1">                   </use></svg><span class="menu_word" style="font-size:17px"> 归档</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-sekuaibiaoqian">                   </use></svg><span class="menu_word" style="font-size:17px"> 标签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-fenlei">                   </use></svg><span class="menu_word" style="font-size:17px"> 分类</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-pinweishenghuo"></use></svg><span class="menu_word" style="font-size:17px"> 休闲</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/life/music/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-yinle">                   </use></svg><span class="menu_word" style="font-size:17px"> 八音盒</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/life/movies/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-dianying1">                   </use></svg><span class="menu_word" style="font-size:17px"> 影院</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/life/games/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-youxishoubing">                   </use></svg><span class="menu_word" style="font-size:17px"> 游戏</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-xiangzi"></use></svg><span class="menu_word" style="font-size:17px"> 八宝箱</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/box/gallery/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-tubiaozhizuomoban">                   </use></svg><span class="menu_word" style="font-size:17px"> 画廊</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/box/animation/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-nvwumao">                   </use></svg><span class="menu_word" style="font-size:17px"> 动画</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/box/nav/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-zhifengche">                   </use></svg><span class="menu_word" style="font-size:17px"> 网址导航</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-shejiaoxinxi"></use></svg><span class="menu_word" style="font-size:17px"> 社交</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/social/fcircle/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-pengyouquan">                   </use></svg><span class="menu_word" style="font-size:17px"> 朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/comments/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-liuyan">                   </use></svg><span class="menu_word" style="font-size:17px"> 留言板</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/social/link/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-lianjie">                   </use></svg><span class="menu_word" style="font-size:17px"> 友人帐</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-wangye"></use></svg><span class="menu_word" style="font-size:17px"> 网站</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/site/census/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon--tongjibiao">                   </use></svg><span class="menu_word" style="font-size:17px"> 网站统计</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/site/echarts/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-shujutongji1">                   </use></svg><span class="menu_word" style="font-size:17px"> 文章统计</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/site/time/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-xianxingshalou">                   </use></svg><span class="menu_word" style="font-size:17px"> 旧时光</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-maoliang"></use></svg><span class="menu_word" style="font-size:17px"> 个人</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/personal/bb/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-qunliaotian">                   </use></svg><span class="menu_word" style="font-size:17px"> 唠叨</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/personal/love/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-love-sign">                   </use></svg><span class="menu_word" style="font-size:17px"> 恋爱小屋</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/personal/about/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-paperplane">                   </use></svg><span class="menu_word" style="font-size:17px"> 关于</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/encryption/%E6%9C%BA%E5%9C%BA/"><svg class="menu_icon faa-tada" aria-hidden="true" style="width:1.30em;height:1.30em;vertical-align:-0.15em;fill:currentColor;overflow:hidden;"><use xlink:href="#icon-paperplane">                   </use></svg><span class="menu_word" style="font-size:17px"> 机场</span></a></li></ul></div></div><center id="name-container"><a id="page-name" href="javascript:scrollToTop()">PAGE_NAME</a></center><div id="nav-right"><div id="search-button"><a class="search faa-parent animated-hover" title="检索站内任何你想要的信息"><svg class="faa-tada icon" style="height:24px;width:24px;fill:currentColor;position:relative;top:6px" aria-hidden="true"><use xlink:href="#icon-valentine_-search-love-find-heart"></use></svg><span> 搜索</span></a></div><a class="meihua faa-parent animated-hover" onclick="toggleWinbox()" title="美化设置-自定义你的风格" id="meihua-button"><svg class="faa-tada icon" style="height:26px;width:26px;fill:currentColor;position:relative;top:8px" aria-hidden="true"><use xlink:href="#icon-tupian1"></use></svg></a><a class="sun_moon faa-parent animated-hover" onclick="switchNightMode()" title="浅色和深色模式转换" id="nightmode-button"><svg class="faa-tada" style="height:25px;width:25px;fill:currentColor;position:relative;top:7px" viewBox="0 0 1024 1024"><use id="modeicon" xlink:href="#icon-moon">       </use></svg></a><div id="toggle-menu"><a><i class="fas fa-bars fa-fw"></i></a></div></div></div></nav><div id="post-info"><h1 class="post-title">SpringBoot</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><svg class="meta_icon post-meta-icon" style="width:30px;height:30px;position:relative;top:10px"><use xlink:href="#icon-rili"></use></svg><span class="post-meta-label">发表于 </span><time class="post-meta-date-created" datetime="2022-06-15T10:01:02.000Z" title="发表于 2022-06-15 18:01:02">2022-06-15</time><span class="post-meta-separator">|</span><svg class="meta_icon post-meta-icon" style="width:18px;height:18px;position:relative;top:5px"><use xlink:href="#icon-gengxin1"></use></svg><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-04-26T09:52:18.155Z" title="更新于 2024-04-26 17:52:18">2024-04-26</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><svg class="meta_icon post-meta-icon" style="width:18px;height:18px;position:relative;top:5px"><use xlink:href="#icon-biaoqian"></use></svg><a class="post-meta-categories" href="/categories/Java/">Java</a><i class="fas fa-angle-right post-meta-separator"></i><svg class="meta_icon post-meta-icon" style="width:18px;height:18px;position:relative;top:5px"><use xlink:href="#icon-biaoqian"></use></svg><a class="post-meta-categories" href="/categories/Java/SpringBoot/">SpringBoot</a><i class="fas fa-angle-right post-meta-separator"></i><svg class="meta_icon post-meta-icon" style="width:18px;height:18px;position:relative;top:5px"><use xlink:href="#icon-biaoqian"></use></svg><a class="post-meta-categories" href="/categories/Java/SpringBoot/SpringBoot%E4%BD%BF%E7%94%A8/">SpringBoot使用</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><svg class="meta_icon post-meta-icon" style="width:25px;height:25px;position:relative;top:8px"><use xlink:href="#icon-charuword"></use></svg><span class="post-meta-label">字数总计:</span><span class="word-count">1.6w</span><span class="post-meta-separator">|</span><svg class="meta_icon post-meta-icon" style="width:20px;height:20px;position:relative;top:5px"><use xlink:href="#icon-shizhong"></use></svg><span class="post-meta-label">阅读时长:</span><span>65分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="SpringBoot"><svg class="meta_icon post-meta-icon" style="width:25px;height:25px;position:relative;top:5px"><use xlink:href="#icon-eye"></use></svg><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div><section class="main-hero-waves-area waves-area"><svg class="waves-svg" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z"></path></defs><g class="parallax"><use href="#gentle-wave" x="48" y="0"></use><use href="#gentle-wave" x="48" y="3"></use><use href="#gentle-wave" x="48" y="5"></use><use href="#gentle-wave" x="48" y="7"></use></g></svg></section></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="SpringBoot-基础入门"><a href="#SpringBoot-基础入门" class="headerlink" title="SpringBoot-基础入门"></a>SpringBoot-基础入门</h1><p><strong>==SpringBoot2和SpringBoot1.x 有区别，一个是基于JDB1.8，一个是基于JDK1.5，具体其他区别可以上网查询资料了解==</strong></p>
<h2 id="一、Spring与SpringBoot"><a href="#一、Spring与SpringBoot" class="headerlink" title="一、Spring与SpringBoot"></a>一、Spring与SpringBoot</h2><h3 id="1、Spring能做什么"><a href="#1、Spring能做什么" class="headerlink" title="1、Spring能做什么"></a>1、Spring能做什么</h3><h4 id="1-1、Spring的能力"><a href="#1-1、Spring的能力" class="headerlink" title="1.1、Spring的能力"></a>1.1、Spring的能力</h4><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/Spring%E7%9A%84%E8%83%BD%E5%8A%9B.webp" alt="Spring的能力"></p>
<h4 id="1-2、Spring的生态"><a href="#1-2、Spring的生态" class="headerlink" title="1.2、Spring的生态"></a>1.2、Spring的生态</h4><ul>
<li>覆盖了：<ul>
<li>web开发</li>
<li>数据访问</li>
<li>安全控制</li>
<li>分布式</li>
<li>消息服务</li>
<li>移动开发</li>
<li>批处理</li>
<li>……</li>
</ul>
</li>
</ul>
<h4 id="1-3、Spring5的重大升级"><a href="#1-3、Spring5的重大升级" class="headerlink" title="1.3、Spring5的重大升级"></a>1.3、Spring5的重大升级</h4><h5 id="1-3-1、响应式编程"><a href="#1-3-1、响应式编程" class="headerlink" title="1.3.1、响应式编程"></a>1.3.1、响应式编程</h5><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B.webp" alt="响应式编程"></p>
<h5 id="1、3、2、内部源码设计"><a href="#1、3、2、内部源码设计" class="headerlink" title="1、3、2、内部源码设计"></a>1、3、2、内部源码设计</h5><p>基于Java8的一些新特性，如：接口默认实现。重新设计源码架构。</p>
<h3 id="2、为什么用SpringBoot"><a href="#2、为什么用SpringBoot" class="headerlink" title="2、为什么用SpringBoot"></a>2、为什么用SpringBoot</h3><blockquote>
<p>Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.</p>
<p>能快速创建出生产级别的Spring应用</p>
</blockquote>
<h4 id="2-1、SpringBoot优点"><a href="#2-1、SpringBoot优点" class="headerlink" title="2.1、SpringBoot优点"></a>2.1、SpringBoot优点</h4><ul>
<li><p>Create stand-alone Spring applications</p>
<ul>
<li>创建独立Spring应用</li>
</ul>
</li>
<li><p>Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)</p>
<ul>
<li>内嵌web服务器</li>
</ul>
</li>
<li><p>Provide opinionated ‘starter’ dependencies to simplify your build configuration</p>
<ul>
<li>自动starter依赖，简化构建配置</li>
</ul>
</li>
<li><p>Automatically configure Spring and 3rd party libraries whenever possible</p>
<ul>
<li>自动配置Spring以及第三方功能</li>
</ul>
</li>
<li><p>Provide production-ready features such as metrics, health checks, and externalized configuration</p>
<ul>
<li>提供生产级别的监控、健康检查及外部化配置</li>
</ul>
</li>
<li><p>Absolutely no code generation and no requirement for XML configuration</p>
<ul>
<li>无代码生成、无需编写XML</li>
</ul>
</li>
</ul>
<blockquote>
<p>SpringBoot是整合Spring技术栈的一站式框架</p>
<p>SpringBoot是简化Spring技术栈的快速开发脚手架</p>
</blockquote>
<h4 id="2-2、SpringBoot的缺点"><a href="#2-2、SpringBoot的缺点" class="headerlink" title="2.2、SpringBoot的缺点"></a>2.2、SpringBoot的缺点</h4><ul>
<li>人称版本帝，迭代快，需要时刻关注变化</li>
<li>封装太深，内部原理复杂，不容易精通</li>
</ul>
<h3 id="3、时代背景"><a href="#3、时代背景" class="headerlink" title="3、时代背景"></a>3、时代背景</h3><h4 id="3-1、微服务"><a href="#3-1、微服务" class="headerlink" title="3.1、微服务"></a>3.1、微服务</h4><p>James Lewis and Martin Fowler (2014)  提出微服务完整概念。<a target="_blank" rel="noopener" href="https://martinfowler.com/microservices/">https://martinfowler.com/microservices/</a></p>
<blockquote>
<p>In short, the microservice architectural style is an approach to developing a single application as a <strong>suite of small services</strong>, each <strong>running in its own process</strong> and communicating with lightweight mechanisms, often an HTTP resource API. These services are <strong>built around business capabilities</strong> and <strong>independently deployable</strong> by fully automated deployment machinery. There is a <strong>bare minimum of centralized management</strong> of these services, which may be written in different programming languages and use different data storage technologies.</p>
<p>简而言之，微服务架构样式是一种将单个应用程序开发为一<strong>组小型服务的方法</strong>，每个<strong>小型服务</strong>都<strong>在自己的进程中运行</strong>并与轻量级机制（通常是HTTP资源API）进行通信。这些服务<strong>围绕业务功能构建，</strong>并且可以 由全自动部署机制<strong>独立部署</strong>。有一个<strong>集中管理的最低限度的</strong>这些服务，可以用不同的编程语言和使用不同的数据存储技术。</p>
</blockquote>
<ul>
<li>微服务是一种架构风格</li>
<li>一个应用拆分为一组小型服务</li>
<li>每个服务运行在自己的进程内，也就是可独立部署和升级</li>
<li>服务之间使用轻量级HTTP交互</li>
<li>服务围绕业务功能拆分</li>
<li>可以由全自动部署机制独立部署</li>
<li>去中心化，服务自治。服务可以使用不同的语言、不同的存储技术</li>
</ul>
<h4 id="3-2、分布式"><a href="#3-2、分布式" class="headerlink" title="3.2、分布式"></a>3.2、分布式</h4><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E5%88%86%E5%B8%83%E5%BC%8F.webp" alt="分布式"></p>
<h5 id="3-2-1、分布式的困难"><a href="#3-2-1、分布式的困难" class="headerlink" title="3.2.1、分布式的困难"></a>3.2.1、分布式的困难</h5><ul>
<li>远程调用</li>
<li>服务发现</li>
<li>负载均衡</li>
<li>服务容错</li>
<li>配置管理</li>
<li>服务监控</li>
<li>链路追踪</li>
<li>日志管理</li>
<li>任务调度</li>
<li>……</li>
</ul>
<h5 id="3-2-2、分布式的解决"><a href="#3-2-2、分布式的解决" class="headerlink" title="3.2.2、分布式的解决"></a>3.2.2、分布式的解决</h5><p><strong>==SpringBoot+SpringCloud==</strong></p>
<p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E5%88%86%E5%B8%83%E5%BC%8F%E8%A7%A3%E5%86%B3.webp" alt="分布式解决"></p>
<h4 id="3-3、云原生"><a href="#3-3、云原生" class="headerlink" title="3.3、云原生"></a>3.3、云原生</h4><h5 id="3-3-1、上云的困难"><a href="#3-3-1、上云的困难" class="headerlink" title="3.3.1、上云的困难"></a>3.3.1、上云的困难</h5><ul>
<li>服务自愈</li>
<li>弹性伸缩</li>
<li>服务隔离</li>
<li>自动化部署</li>
<li>灰度发布</li>
<li>流量治理</li>
<li>……</li>
</ul>
<h5 id="3-3-2、上云的解决"><a href="#3-3-2、上云的解决" class="headerlink" title="3.3.2、上云的解决"></a>3.3.2、上云的解决</h5><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E4%B8%8A%E4%BA%91%E7%9A%84%E8%A7%A3%E5%86%B3.webp" alt="上云的解决"></p>
<h3 id="4、如何学习SpringBoot"><a href="#4、如何学习SpringBoot" class="headerlink" title="4、如何学习SpringBoot"></a>4、如何学习SpringBoot</h3><blockquote>
<p>官网文档<a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/">https://docs.spring.io/spring-boot/docs/current/reference/html/</a></p>
</blockquote>
<h4 id="4-1、官网文档架构"><a href="#4-1、官网文档架构" class="headerlink" title="4.1、官网文档架构"></a>4.1、官网文档架构</h4><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A31.webp" alt="参考文档2"></p>
<p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A32.webp" alt="参考文档2"></p>
<h4 id="4-2、查看版本新特性"><a href="#4-2、查看版本新特性" class="headerlink" title="4.2、查看版本新特性"></a>4.2、查看版本新特性</h4><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E7%89%88%E6%9C%AC%E6%96%B0%E7%89%B9%E6%80%A7.webp" alt="版本新特性"></p>
<h2 id="二、SpringBoot入门"><a href="#二、SpringBoot入门" class="headerlink" title="二、SpringBoot入门"></a>二、SpringBoot入门</h2><h3 id="1、系统要求"><a href="#1、系统要求" class="headerlink" title="1、系统要求"></a>1、系统要求</h3><ul>
<li>java8 &amp; 兼容java14 .</li>
<li>Maven 3.3+</li>
</ul>
<h4 id="1-1、Maven设置"><a href="#1-1、Maven设置" class="headerlink" title="1.1、Maven设置"></a>1.1、Maven设置</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 设置仓库的路径 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">localRepository</span>&gt;</span>  <span class="comment">&lt;!-- 仓库的路径 --&gt;</span>  <span class="tag">&lt;/<span class="name">localRepository</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">mirrors</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 配置阿里云的镜像 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mirror</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span>&gt;</span>nexus-aliyun<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">mirrorOf</span>&gt;</span>central<span class="tag">&lt;/<span class="name">mirrorOf</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>Nexus aliyun<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://maven.aliyun.com/nexus/content/groups/public<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">mirror</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mirrors</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">profiles</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 配置JDK的版本 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">profile</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span>&gt;</span>jdk-1.8<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">activation</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">activeByDefault</span>&gt;</span>true<span class="tag">&lt;/<span class="name">activeByDefault</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">jdk</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">jdk</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">activation</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">maven.compiler.source</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">maven.compiler.source</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">maven.compiler.target</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">maven.compiler.target</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">maven.compiler.compilerVersion</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">maven.compiler.compilerVersion</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">profile</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">profiles</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="2、第一个SpringBoot项目"><a href="#2、第一个SpringBoot项目" class="headerlink" title="2、第一个SpringBoot项目"></a>2、第一个SpringBoot项目</h3><h4 id="2-1、创建Maven项目"><a href="#2-1、创建Maven项目" class="headerlink" title="2.1、创建Maven项目"></a>2.1、创建Maven项目</h4><p><strong>后面还有其他创建SpringBoot项目的方式</strong></p>
<h4 id="2-2、引入依赖"><a href="#2-2、引入依赖" class="headerlink" title="2.2、引入依赖"></a>2.2、引入依赖</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.4.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="2-3、创建主程序"><a href="#2-3、创建主程序" class="headerlink" title="2.3、创建主程序"></a>2.3、创建主程序</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//主程序类，注意主启动类的位置</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span><span class="comment">//告诉SpringBoot这是一个SpringBoot应用</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MainApplication</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">//固定写法</span></span><br><span class="line">        SpringApplication.run(MainApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="2-4、测试"><a href="#2-4、测试" class="headerlink" title="2.4、测试"></a>2.4、测试</h4><p><strong>直接运行主程序</strong></p>
<h4 id="2-5、简化配置"><a href="#2-5、简化配置" class="headerlink" title="2.5、简化配置"></a>2.5、简化配置</h4><p><strong>==为了将简化配置，可以将所有配置全部写到一个配置文件中，文件名默认为：application.properties==</strong></p>
<blockquote>
<p><strong>文件的具体使用方法可以去下面地址查询使用方法：</strong></p>
<p><strong><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html">https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html</a></strong></p>
</blockquote>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#设置Tomcat启动的端口号，创建一个application.properties文件用来修改SpringBoot的配置</span></span><br><span class="line"><span class="attr">server.port</span>=<span class="string">8888</span></span><br></pre></td></tr></table></figure>
<h4 id="2-6、简化配置"><a href="#2-6、简化配置" class="headerlink" title="2.6、简化配置"></a>2.6、简化配置</h4><ul>
<li><p>在pom.xml配置文件中继续添加以下配置</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>使用Maven的生命周期将Maven项目clean、package，将项目打包成为可执行的jar包</p>
  <figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">找到打包的<span class="keyword">jar包目录下打开cmd，使用Java的命令执行jar包</span></span><br><span class="line"><span class="keyword"></span><span class="keyword">java </span>-<span class="keyword">jar </span>【打包的<span class="keyword">jar包的文件名】</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>注意点：如果不能启动，可以尝试取消cmd的快速编辑模式，怎么取消cmd的快速编辑模式可以上网查询</p>
</li>
</ul>
<h2 id="三、了解自动配置原理"><a href="#三、了解自动配置原理" class="headerlink" title="三、了解自动配置原理"></a>三、了解自动配置原理</h2><h3 id="1、SpringBoot特点"><a href="#1、SpringBoot特点" class="headerlink" title="1、SpringBoot特点"></a>1、SpringBoot特点</h3><h4 id="1-1、依赖管理"><a href="#1-1、依赖管理" class="headerlink" title="1.1、依赖管理"></a>1.1、依赖管理</h4><ul>
<li><p>父项目做依赖管理</p>
<p>  从SpringBoot入门能了解到，Maven的pom.xml文件需要导入SpringBoot的依赖</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 依赖管理 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.4.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment"> spring-boot-starter-parent的父项目</span></span><br><span class="line"><span class="comment">几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制</span></span><br><span class="line"><span class="comment"> --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-dependencies<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.4.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>开发导入starter场景启动器</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 导入SpringWeb开发所需要的包 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">1、</span><br><span class="line">当导入依赖的时候，artifactId标签中填写的一般是  spring-boot-starter-* ： *就某种场景</span><br><span class="line">例如：spring-boot-starter-web，导入的是SpringWeb开发的场景</span><br><span class="line">spring-boot-starter-test，导入的是代码测试环境所需要的开发环境</span><br><span class="line">其他场景可以去官网查询：https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter</span><br><span class="line"></span><br><span class="line">2、只要引入starter，这个场景的所有常规需要的依赖我们都自动引入</span><br><span class="line"></span><br><span class="line">3、SpringBoot所有支持的场景</span><br><span class="line"></span><br><span class="line">4、见到的  *-spring-boot-starter： 第三方为我们提供的简化开发的场景启动器。</span><br><span class="line">例如：MyBatisPlus的：mybatis-plus-boot-starter</span><br><span class="line"></span><br><span class="line">5、所有场景启动器最底层的依赖</span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.4.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>compile<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>无需关注版本号，自动版本仲裁</p>
<ul>
<li>引入依赖默认都可以不写版本</li>
<li>引入非版本仲裁的jar，要写版本号。</li>
</ul>
</li>
<li><p>可以修改默认版本号</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。</span><br><span class="line">2、在当前项目里面重写配置,</span><br><span class="line"><span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--  Spring  --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mysql.version</span>&gt;</span>8.0.19<span class="tag">&lt;/<span class="name">mysql.version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="1-2、自动配置"><a href="#1-2、自动配置" class="headerlink" title="1.2、自动配置"></a>1.2、自动配置</h4><ul>
<li><p>自动配置好Tomcat</p>
<ul>
<li><p>引入Tomcat依赖</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 方式一 --&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 第一步 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.4.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 第二步，引入web开发所需要的所有东西 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 方式二，只引入Tomcat --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-tomcat<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.4.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>compile<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>配置Tomcat</p>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>自动配置好SpringMVC</p>
<ul>
<li>引入SpringMVC全套组件（如web.xml文件中的dispatchServlet，文件上传的：StandardServletMultipartResolver，等等）</li>
<li>自动配好SpringMVC常用组件（功能）</li>
</ul>
</li>
</ul>
<ul>
<li><p>自动配置好Web常见功能，如：字符编码问题</p>
<ul>
<li>SpringBoot帮我们配置好了所有web开发的常见场景</li>
</ul>
</li>
</ul>
<ul>
<li><p>默认的包结构</p>
<ul>
<li><p>主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来，如果所在包的级别大于主程序，那么将不会被扫描出来，如果需要扫描，则改变默认的扫描的路径</p>
</li>
<li><p>无需以前的包扫描配置</p>
</li>
<li><p>想要改变扫描路径</p>
<ul>
<li><p>@SpringBootApplication(scanBasePackages=”com.atguigu”)</p>
</li>
<li><p>或者@ComponentScan 指定扫描路径，具体使用可以去找Spring注解驱动开发的笔记，或找后面的笔记</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span><span class="comment">//告诉SpringBoot这是一个SpringBoot应用</span></span><br><span class="line"><span class="comment">//通过查看@SpringBootApplication注解可以知道，上面一个注解相当于下面三个注解</span></span><br><span class="line"><span class="meta">@SpringBootConfiguration</span></span><br><span class="line"><span class="meta">@EnableAutoConfiguration</span></span><br><span class="line"><span class="meta">@ComponentScan</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li>各种配置拥有默认值<ul>
<li>默认配置最终都是映射到某个类上，如：MultipartProperties</li>
<li>配置文件的值最终会绑定每个类上，这个类会在容器中创建对象</li>
</ul>
</li>
</ul>
<ul>
<li>按需加载所有自动配置项<ul>
<li>Spring中有非常多的starter</li>
<li>引入了哪些场景这个场景的自动配置才会开启</li>
<li>SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面</li>
</ul>
</li>
<li>……….</li>
</ul>
<h3 id="2、容器组件功能"><a href="#2、容器组件功能" class="headerlink" title="2、容器组件功能"></a>2、容器组件功能</h3><h4 id="2-1、组件添加"><a href="#2-1、组件添加" class="headerlink" title="2.1、组件添加"></a>2.1、组件添加</h4><p>==<strong>这里的组件添的部分简单使用方法，在Spring注解驱动开发的笔记中还有以下复杂的用发，该笔记中也有Spring注解驱动开发中没有的部分，两者笔记可以相互借鉴使用</strong>==</p>
<h5 id="2-1-1、Configuration"><a href="#2-1-1、Configuration" class="headerlink" title="2.1.1、Configuration"></a>2.1.1、Configuration</h5><ul>
<li><p>基本使用</p>
</li>
<li><p>Full模式与Lite模式</p>
<ul>
<li><p>最佳实战</p>
<ul>
<li>配置类组件之间没有依赖关系用Lite模式，加速容器启动，减少判断<strong>（同一个配置类之间的Bean没有相互调用的关系使用Lite模式）</strong></li>
<li>配置类组件之间有依赖关系，方法会被调用得到之前的单实例，用Full<strong>（同一个配置类之间的Bean有相互调用的关系使用Full模式）</strong></li>
</ul>
</li>
<li><p>实例</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 1、配置类里面使用<span class="doctag">@Bean</span>注解标注在方法上给容器注册组件，默认也是单实例的</span></span><br><span class="line"><span class="comment"> * 2、配置类本身也是组件</span></span><br><span class="line"><span class="comment"> * 3、<span class="doctag">@Configuration</span>注解中有个属性proxyBeanMethods默认值为true：代理Bean方法，</span></span><br><span class="line"><span class="comment"> * 		设置为true，每次获取Bean的时候都会检查容器是否有该Bean，设置为false，不会检查是否有该Bean</span></span><br><span class="line"><span class="comment"> *     		 Full(proxyBeanMethods = true)、【保证每个<span class="doctag">@Bean</span>方法被调用多少次返回的组件都是单实例的】</span></span><br><span class="line"><span class="comment"> *      	 Lite(proxyBeanMethods = false)【每个<span class="doctag">@Bean</span>方法被调用多少次返回的组件都是新创建的】</span></span><br><span class="line"><span class="comment"> *      	 组件依赖必须使用Full模式默认。其他默认是否Lite模式</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Configuration</span><span class="comment">//告诉SpringBoot这是一个配置类 == Spring的配置文件</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span><span class="comment">//给容器中添加组件，以方法名作为组件的id，返回类型就是组件类型，返回的值，就是组件在容器中的示例</span></span><br><span class="line">    <span class="keyword">public</span> User <span class="title function_">user</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;张三&quot;</span>, <span class="number">18</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span><span class="comment">//给容器中添加组件，以方法名作为组件的id，返回类型就是组件类型，返回的值，就是组件在容器中的示例</span></span><br><span class="line">    <span class="keyword">public</span> Pet <span class="title function_">pet</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Pet</span>(<span class="string">&quot;Tomcat&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
<h5 id="2-1-2、-Bean、-Component、-Controller、-Service、-Repository"><a href="#2-1-2、-Bean、-Component、-Controller、-Service、-Repository" class="headerlink" title="2.1.2、@Bean、@Component、@Controller、@Service、@Repository"></a>2.1.2、@Bean、@Component、@Controller、@Service、@Repository</h5><h5 id="2-1-3、-ComponentScan、-Import"><a href="#2-1-3、-ComponentScan、-Import" class="headerlink" title="2.1.3、@ComponentScan、@Import"></a>2.1.3、@ComponentScan、@Import</h5><p>==<strong>这里只有@Import注解的简单使用，在Spring注解驱动开发中还有其他一些高级的用法</strong>==</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//@Import(&#123;User.class, DataSource.class&#125;)  给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名</span></span><br><span class="line"><span class="meta">@Configuration</span><span class="comment">//告诉SpringBoot这是一个配置类 == Spring的配置文件</span></span><br><span class="line"><span class="meta">@Import(&#123;Car.class, DataSource.class&#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyConfig</span> &#123;  &#125;</span><br></pre></td></tr></table></figure>
<h5 id="2-1-4、-Conditional"><a href="#2-1-4、-Conditional" class="headerlink" title="2.1.4、@Conditional"></a>2.1.4、@Conditional</h5><ul>
<li>条件装配：满足Conditional指定的条件，则进行组件注入</li>
</ul>
<p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/Conditional.webp" alt="Conditional"></p>
<ul>
<li><p>@Conditional测试：</p>
<p>  这里只测试@Conditional的子注解@<code>ConditionalOnBean</code>和<code>@ConditionalOnMissingBean</code></p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span><span class="comment">//告诉SpringBoot这是一个配置类 == Spring的配置文件</span></span><br><span class="line"><span class="comment">//@ConditionalOnBean(name = &quot;user&quot;)//当配置类中有name为user的bean的时候，该配置类不起作用，可以写在方法上和类上</span></span><br><span class="line"><span class="meta">@ConditionalOnMissingBean(name = &quot;user&quot;)</span><span class="comment">//当配置类中没有name为user的bean的时候，该配置类不起作用，可以写在方法上和类上</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyConfig</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Bean</span><span class="comment">//给容器中添加组件，以方法名作为组件的id，返回类型就是组件类型，返回的值，就是组件在容器中的示例</span></span><br><span class="line">    <span class="keyword">public</span> User <span class="title function_">user</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;张三&quot;</span>, <span class="number">18</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span><span class="comment">//给容器中添加组件，以方法名作为组件的id，返回类型就是组件类型，返回的值，就是组件在容器中的示例</span></span><br><span class="line">    <span class="keyword">public</span> Pet <span class="title function_">pet</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Pet</span>(<span class="string">&quot;Tomcat&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>测试：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="comment">//返回IOC容器</span></span><br><span class="line">    <span class="type">ConfigurableApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> SpringApplication.run(MainApplication.class, args);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//2、查看容器里面的组件，获取组件中的全部容器</span></span><br><span class="line">    String[] names = context.getBeanDefinitionNames();</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//3、从容器中获取组件，如果有类型为User的Bean将不报错，如果报错，则没有类型为User的Bean</span></span><br><span class="line">    context.getBean(User.class);</span><br><span class="line">    <span class="comment">//System.out.println(context.getBean(Car.class));</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="2-2、原生配置文件引入"><a href="#2-2、原生配置文件引入" class="headerlink" title="2.2、原生配置文件引入"></a>2.2、原生配置文件引入</h4><p>==<strong>引入Spring的配置文件</strong>==</p>
<h5 id="2-2-1、-ImportResource"><a href="#2-2-1、-ImportResource" class="headerlink" title="2.2.1、@ImportResource"></a>2.2.1、@ImportResource</h5><blockquote>
<p><strong>格式：@ImportResource(“classpath:文件”)</strong></p>
</blockquote>
<ul>
<li><p>Spring的原生配置文件：applicationContext.xml</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans </span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;user01&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.lf.boot.pojo.User&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>SpringBoot配置类引入applicationContext.xml配置文件</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span><span class="comment">//告诉SpringBoot这是一个配置类 == Spring的配置文件</span></span><br><span class="line"><span class="comment">//@ConditionalOnBean(name = &quot;user&quot;)//当配置类中有name为user的bean的时候，该配置类不起作用，可以写在方法上和类上</span></span><br><span class="line"><span class="meta">@ConditionalOnMissingBean(name = &quot;user&quot;)</span><span class="comment">//当配置类中没有name为user的bean的时候，该配置类不起作用，可以写在方法上和类上</span></span><br><span class="line"><span class="meta">@ImportResource(&quot;classpath:applicationContext.xml&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span><span class="comment">//给容器中添加组件，以方法名作为组件的id，返回类型就是组件类型，返回的值，就是组件在容器中的示例</span></span><br><span class="line">    <span class="keyword">public</span> User <span class="title function_">user</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;张三&quot;</span>, <span class="number">18</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span><span class="comment">//给容器中添加组件，以方法名作为组件的id，返回类型就是组件类型，返回的值，就是组件在容器中的示例</span></span><br><span class="line">    <span class="keyword">public</span> Pet <span class="title function_">pet</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Pet</span>(<span class="string">&quot;Tomcat&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="2-3、properties配置绑定"><a href="#2-3、properties配置绑定" class="headerlink" title="2.3、properties配置绑定"></a>2.3、properties配置绑定</h4><p>如何使用Java读取到properties文件中的内容，并且把它封装到JavaBean中，以供随时使用；</p>
<ul>
<li><p>使用Java的原生方法</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test1</span> &#123;</span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">getProperties</span> &#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> FileNotFoundException, IOException &#123;</span><br><span class="line">            <span class="type">Properties</span> <span class="variable">pps</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Properties</span>();</span><br><span class="line">            pps.load(<span class="keyword">new</span> <span class="title class_">FileInputStream</span>(<span class="string">&quot;a.properties&quot;</span>));</span><br><span class="line">            <span class="type">Enumeration</span> <span class="variable">enum1</span> <span class="operator">=</span> pps.propertyNames();<span class="comment">//得到配置文件的名字</span></span><br><span class="line">            <span class="keyword">while</span>(enum1.hasMoreElements()) &#123;</span><br><span class="line">                <span class="type">String</span> <span class="variable">strKey</span> <span class="operator">=</span> (String) enum1.nextElement();</span><br><span class="line">                <span class="type">String</span> <span class="variable">strValue</span> <span class="operator">=</span> pps.getProperty(strKey);</span><br><span class="line">                System.out.println(strKey + <span class="string">&quot;=&quot;</span> + strValue);</span><br><span class="line">                <span class="comment">//封装到JavaBean。</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="2-3-1、-ConfigurationProperties-Component"><a href="#2-3-1、-ConfigurationProperties-Component" class="headerlink" title="2.3.1、@ConfigurationProperties + @Component"></a>2.3.1、@ConfigurationProperties + @Component</h5><blockquote>
<p><strong>@ConfigurationProperties，使用该注解必须要将前缀传入 prefix = “前缀名” </strong></p>
<p><strong>@Component</strong></p>
<p><strong>两个注解需要同时写在JavaBean上</strong></p>
<p><strong>想使用该注解需要将使用的类添加到Spring中，可以加上@component注解将类加入Spring中</strong></p>
<p><strong>该注解可以让JavaBean和properties配置文件绑定，让Spring给JavaBean中的属性自动赋值，值的数据从properties文件中获取</strong></p>
</blockquote>
<ul>
<li><p>properties属性文件：</p>
  <figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mycar.brand</span>=<span class="string">测试</span></span><br><span class="line"><span class="attr">mycar.price</span>=<span class="string">999</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>JavaBean</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lf.boot.pojo;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.context.properties.ConfigurationProperties;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 只有在容器中的组件，才会拥有SpringBoot提供的强大功能</span></span><br><span class="line"><span class="comment"> * 只有将类交给Spring管理才能使用<span class="doctag">@ConfigurationProperties</span>注解</span></span><br><span class="line"><span class="comment"> * prefix：如果properties文件中对应的属性有前缀，可以使用该属性传入前缀的值，在给属性自动赋值的时候后就会自动将前缀的字符和属性的字符连接起来  去配置文件中寻找，如果没有前缀，直接把注解加上就行了</span></span><br><span class="line"><span class="comment"> * 注意：需要有对应的get和set方法</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;mycar&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Car</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String brand;</span><br><span class="line">    <span class="keyword">private</span> Integer price;</span><br><span class="line">	<span class="comment">// .......对应的get和set方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>测试：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//@RestController 注解相当于 @ResponseBody 和 @requestMapping两个注解的结合的使用，</span></span><br><span class="line"><span class="comment">//使用了@RestController注解的类下的所有方法返回的东西全部输出在浏览器的页面上</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloController</span> &#123;</span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> Car car;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@RequestMapping(&quot;/car&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Car <span class="title function_">car</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> car;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="2-3-2、-EnableConfigurationProperties-ConfigurationProperties"><a href="#2-3-2、-EnableConfigurationProperties-ConfigurationProperties" class="headerlink" title="2.3.2、@EnableConfigurationProperties + @ConfigurationProperties"></a>2.3.2、@EnableConfigurationProperties + @ConfigurationProperties</h5><blockquote>
<p><strong>@EnableConfigurationProperties，该注解写在配置类上</strong></p>
<p><strong>@ConfigurationProperties，该注解写在JavaBean上</strong></p>
<p><strong>@EnableConfigurationProperties(哪个类需要开启的属性的配置的.class)</strong></p>
<p><strong>作用</strong></p>
<p>​    <strong>一：开启配置绑定功能</strong></p>
<p>​    <strong>二：把传入的组件自动注册到容器中</strong></p>
</blockquote>
<ul>
<li><p>properties属性文件：</p>
  <figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mycar.brand</span>=<span class="string">测试</span></span><br><span class="line"><span class="attr">mycar.price</span>=<span class="string">999</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>JavaBean</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lf.boot.pojo;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.context.properties.ConfigurationProperties;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 只有在容器中的组件，才会拥有SpringBoot提供的强大功能</span></span><br><span class="line"><span class="comment"> * 只有将类交给Spring管理才能使用<span class="doctag">@ConfigurationProperties</span>注解</span></span><br><span class="line"><span class="comment"> * prefix：如果properties文件中对应的属性有前缀，可以使用该属性传入前缀的值，在给属性自动赋值的时候后就会自动将前缀的字符和属性的字符连接起来  去配置文件中寻找，如果没有前缀，直接把注解加上就行了</span></span><br><span class="line"><span class="comment"> * 注意：需要有对应的get和set方法</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;mycar&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Car</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String brand;</span><br><span class="line">    <span class="keyword">private</span> Integer price;</span><br><span class="line">	<span class="comment">// .......对应的get和set方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>配置类：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span><span class="comment">//告诉SpringBoot这是一个配置类 == Spring的配置文件</span></span><br><span class="line"><span class="meta">@EnableConfigurationProperties(Car.class)</span></span><br><span class="line"><span class="comment">//1、开启Car配置绑定功能</span></span><br><span class="line"><span class="comment">//2、把这个Car这个组件自动注册到容器中</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyConfig</span> &#123; &#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>测试：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//@RestController 注解相当于 @ResponseBody 和 @requestMapping两个注解的结合的使用，</span></span><br><span class="line"><span class="comment">//使用了@RestController注解的类下的所有方法返回的东西全部输出在浏览器的页面上</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloController</span> &#123;</span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> Car car;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@RequestMapping(&quot;/car&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Car <span class="title function_">car</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> car;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="3、自动配置原理入门"><a href="#3、自动配置原理入门" class="headerlink" title="3、自动配置原理入门"></a>3、自动配置原理入门</h3><h4 id="3-1、引导加载自动配置类"><a href="#3-1、引导加载自动配置类" class="headerlink" title="3.1、引导加载自动配置类"></a>3.1、引导加载自动配置类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootConfiguration</span></span><br><span class="line"><span class="meta">@EnableAutoConfiguration</span></span><br><span class="line"><span class="meta">@ComponentScan(excludeFilters = &#123; @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),</span></span><br><span class="line"><span class="meta">		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) &#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> SpringBootApplication &#123;  &#125; </span><br></pre></td></tr></table></figure>
<h5 id="3-1-1、-SpringBootConfiguration"><a href="#3-1-1、-SpringBootConfiguration" class="headerlink" title="3.1.1、@SpringBootConfiguration"></a>3.1.1、@SpringBootConfiguration</h5><p>​        <strong>查看@SpringBootConfiguration注解的源码，发现里面有@Configuration（标注配置类的注解）这个注解。代表当前是一个配置类</strong></p>
<h5 id="3-1-2、-ComponentScan"><a href="#3-1-2、-ComponentScan" class="headerlink" title="3.1.2、@ComponentScan"></a>3.1.2、@ComponentScan</h5><p><strong>指定扫描哪些包，具体使用可以看Spring注解驱动开发的笔记</strong></p>
<h5 id="3-1-3、-EnableAutoConfiguration"><a href="#3-1-3、-EnableAutoConfiguration" class="headerlink" title="3.1.3、@EnableAutoConfiguration"></a>3.1.3、@EnableAutoConfiguration</h5><ul>
<li><p><strong>@EnableAutoConfiguration注解源码：</strong></p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@AutoConfigurationPackage</span></span><br><span class="line"><span class="meta">@Import(AutoConfigurationImportSelector.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> EnableAutoConfiguration &#123;   &#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<pre><code>- @AutoConfigurationPackage（自动配置包）

    <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Import(AutoConfigurationPackages.Registrar.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> AutoConfigurationPackage &#123;   &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//该注解利用register给容器中添加一系列组件</span></span><br><span class="line"><span class="comment">//将指定的一个包下的所有组件导入进来？MainApplication 所在包下。</span></span><br></pre></td></tr></table></figure>

- @Import(AutoConfigurationImportSelector.class)
</code></pre><h4 id="3-2、按需开启自动配置项"><a href="#3-2、按需开启自动配置项" class="headerlink" title="3.2、按需开启自动配置项"></a>3.2、按需开启自动配置项</h4><h4 id="3-3、修改默认配置"><a href="#3-3、修改默认配置" class="headerlink" title="3.3、修改默认配置"></a>3.3、修改默认配置</h4><p>==<strong>修改application.properties配置文件</strong>==</p>
<h4 id="3-4、最佳实践"><a href="#3-4、最佳实践" class="headerlink" title="3.4、最佳实践"></a>3.4、最佳实践</h4><ul>
<li><p>引入场景依赖：starter启动器</p>
<p>  <a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter">https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter</a></p>
</li>
<li><p>查看自动配置了哪些</p>
<ul>
<li>自己分析：引入场景</li>
<li>application.properties配置文件中设置 debug=true 开启自动配置报告</li>
</ul>
</li>
<li><p>是否按需修改</p>
<ul>
<li><p>参照文档修改配置项</p>
<p>  <a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties">https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties</a></p>
<ul>
<li>自己分析，xxxProperties绑定了配置文件的哪些</li>
</ul>
</li>
<li><p>自定义加入或者替换组件</p>
<ul>
<li>@Bean、@Component</li>
</ul>
</li>
<li><p>自定义器  <strong>XXXXXCustomizer</strong>；</p>
</li>
<li><p>……….</p>
</li>
</ul>
</li>
</ul>
<h3 id="4、开发小技巧"><a href="#4、开发小技巧" class="headerlink" title="4、开发小技巧"></a>4、开发小技巧</h3><h4 id="4-1、Lombok"><a href="#4-1、Lombok" class="headerlink" title="4.1、Lombok"></a>4.1、Lombok</h4><ul>
<li><p>第一步：在idea中下载Lombok插件</p>
</li>
<li><p>第二步：在Maven中添加依赖</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--简化开发，快速生成get和set方法，不需要写版本号，SpringBoot已经管理了该包的版本--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>  <img src= "" data-lazy-src="https://www.naste.top:9000/webp/Lombok%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3.webp" alt="Lombok常用注解"></p>
</li>
</ul>
<h4 id="4-2、dev-tools"><a href="#4-2、dev-tools" class="headerlink" title="4.2、dev-tools"></a>4.2、dev-tools</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--devtools热部署--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-devtools<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">optional</span>&gt;</span>true<span class="tag">&lt;/<span class="name">optional</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>true<span class="tag">&lt;/<span class="name">scope</span>&gt;</span>  <span class="comment">&lt;!-- 需要设置为true，否则不生效--&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>项目或者页面修改以后：Ctrl+F9；</p>
<p>还可以使用 JRebel 插件，该插件在系统用户为中文的时候不能使用</p>
<h4 id="4-3、Spring-Initailizr（项目初始化向导）"><a href="#4-3、Spring-Initailizr（项目初始化向导）" class="headerlink" title="4.3、Spring Initailizr（项目初始化向导）"></a>4.3、Spring Initailizr（项目初始化向导）</h4><p>使用idea的项目初始化向导，能选择我们需要的开发场景、自动依赖引入、自动创建项目结构、自动编写好主配置类</p>
<ul>
<li><p>使用初始化向导创建项目</p>
<p>  <img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E5%88%9D%E5%A7%8B%E5%8C%96%E5%90%91%E5%AF%BC.webp" alt="初始化向导"></p>
</li>
</ul>
<ul>
<li><p>项目目录结构</p>
<p>  <img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E9%A1%B9%E7%9B%AE%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84.webp" alt="项目目录结构"></p>
</li>
</ul>
<h1 id="SpringBoot-核心功能"><a href="#SpringBoot-核心功能" class="headerlink" title="SpringBoot-核心功能"></a>SpringBoot-核心功能</h1><h2 id="一、配置文件"><a href="#一、配置文件" class="headerlink" title="一、配置文件"></a>一、配置文件</h2><p>==<strong>具体的实现看1.2.4实例</strong>==</p>
<h3 id="1、文件类型"><a href="#1、文件类型" class="headerlink" title="1、文件类型"></a>1、文件类型</h3><h4 id="1-1、properties"><a href="#1-1、properties" class="headerlink" title="1.1、properties"></a>1.1、properties</h4><p>和以前的properties配置文件的写法一样</p>
<h4 id="1-2、yaml"><a href="#1-2、yaml" class="headerlink" title="1.2、yaml"></a>1.2、yaml</h4><h5 id="1-2-1、简介"><a href="#1-2-1、简介" class="headerlink" title="1.2.1、简介"></a>1.2.1、简介</h5><p>YAML 是 “YAML Ain’t Markup Language”（YAML 不是一种标记语言）的递归缩写。在开发的这种语言时，YAML 的意思其实是：”Yet Another Markup Language”（仍是一种标记语言）。 </p>
<p>yaml文件非常适合来做以数据中心的配置文件</p>
<h5 id="1-2-2、基本语法"><a href="#1-2-2、基本语法" class="headerlink" title="1.2.2、基本语法"></a>1.2.2、基本语法</h5><ul>
<li>key: value；kv之间有空格</li>
<li>大小写敏感</li>
<li>使用缩进表示层级关系</li>
<li><strong>缩进不允许使用tab，只允许空格</strong></li>
<li>缩进的空格数不重要，只要相同层级的元素左对齐即可</li>
<li>‘#’表示注释</li>
<li>字符串无需加引号，如果要加，’’与””表示字符串内容 会被 转义/不转义</li>
</ul>
<h5 id="1-2-3、数据类型"><a href="#1-2-3、数据类型" class="headerlink" title="1.2.3、数据类型"></a>1.2.3、数据类型</h5><p>==<strong>: 后面需要有空格</strong>==</p>
<ul>
<li><p>字面量：单个的、不可再分的值。date、boolean、string、number、null</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">k:</span> <span class="string">v</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>对象：键值对的集合。map、hash、set、object </p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">行内写法：</span>  <span class="attr">k:</span> &#123;<span class="string">k1:v1</span>,<span class="string">k2:v2</span>,<span class="string">k3:v3</span>&#125;</span><br><span class="line"><span class="comment">#或</span></span><br><span class="line"><span class="attr">k:</span> </span><br><span class="line">  <span class="attr">k1:</span> <span class="string">v1</span></span><br><span class="line">  <span class="attr">k2:</span> <span class="string">v2</span></span><br><span class="line">  <span class="attr">k3:</span> <span class="string">v3</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>数组：一组按次序排列的值。array、list、queue</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">行内写法：</span>  <span class="attr">k:</span> [<span class="string">v1</span>,<span class="string">v2</span>,<span class="string">v3</span>]</span><br><span class="line"><span class="comment">#或者</span></span><br><span class="line"><span class="attr">k:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">v1</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">v2</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">v3</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="1-2-4、实例"><a href="#1-2-4、实例" class="headerlink" title="1.2.4、实例"></a>1.2.4、实例</h5><ul>
<li><p>JavaBean环境</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;person&quot;)</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String username;</span><br><span class="line">    <span class="keyword">private</span> Boolean boss;</span><br><span class="line">    <span class="keyword">private</span> Date birth;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> String[] interests;</span><br><span class="line">    <span class="keyword">private</span> List&lt;String&gt; animal;</span><br><span class="line">    <span class="keyword">private</span> Map&lt;String, Object&gt; score;</span><br><span class="line">    <span class="keyword">private</span> Set&lt;Double&gt; salaries;</span><br><span class="line">    <span class="keyword">private</span> Pet pet;</span><br><span class="line">    <span class="keyword">private</span> List&lt;Pet&gt; pets;</span><br><span class="line">    <span class="keyword">private</span> Map&lt;String, List&lt;Pet&gt;&gt; allPets;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// ==================================================================</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Pet</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Double weight;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>yaml文件</p>
<ul>
<li><p>String、Boolean、Integer、Date 等类型的数据</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#最前面加一个person，代表下面所有的变量将会加上person这个前缀</span></span><br><span class="line"><span class="attr">person:</span></span><br><span class="line">  <span class="comment">#String类型写法</span></span><br><span class="line">  <span class="attr">username:</span> <span class="string">韩信</span></span><br><span class="line">  <span class="comment">#Boolean类型</span></span><br><span class="line">  <span class="attr">boss:</span> <span class="literal">true</span></span><br><span class="line">  <span class="comment">#日期类型</span></span><br><span class="line">  <span class="attr">birth:</span> <span class="number">2021</span><span class="string">/2/2</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>数组、List&lt;基本类型和包装类型&gt;、Set&lt; 基本类型和包装类型 &gt;</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#最前面加一个person，代表下面所有的变量将会加上person这个前缀</span></span><br><span class="line"><span class="attr">person:</span></span><br><span class="line">  <span class="comment">#方式一：</span></span><br><span class="line">  <span class="attr">interests:</span> [<span class="string">篮球</span>,<span class="string">足球</span>]</span><br><span class="line">  <span class="comment">#方式二：通过 - 来区分数据，每个 - 都代表一个值</span></span><br><span class="line">  <span class="attr">interests:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">羽毛球</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">乒乓球</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>Map集合：Map&lt; 基本类型等包装类型 , 基本类型等包装类型 &gt;</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#最前面加一个person，代表下面所有的变量将会加上person这个前缀</span></span><br><span class="line"><span class="attr">person:</span></span><br><span class="line">  <span class="comment">#Map集合：Map&lt;String, 基本类型等包装类型&gt;</span></span><br><span class="line">  <span class="comment">#Map集合写法一：JSON格式写法</span></span><br><span class="line">  <span class="attr">score:</span> &#123;<span class="attr">english:</span> <span class="number">70</span> , <span class="attr">math:</span> <span class="number">90</span>&#125;</span><br><span class="line">  <span class="comment">#Map集合写法二：一行一个 key: value</span></span><br><span class="line">  <span class="attr">score:</span></span><br><span class="line">    <span class="attr">english:</span> <span class="number">60</span></span><br><span class="line">    <span class="attr">math:</span> <span class="number">80</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>对象类型（JavaBean）</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#最前面加一个person，代表下面所有的变量将会加上person这个前缀</span></span><br><span class="line"><span class="attr">person:</span></span><br><span class="line">  <span class="attr">pet:</span></span><br><span class="line">    <span class="string">属性:</span> <span class="string">值</span></span><br><span class="line">    <span class="string">属性:</span> <span class="string">值</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>List&lt; JavaBean &gt;</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#最前面加一个person，代表下面所有的变量将会加上person这个前缀</span></span><br><span class="line"><span class="attr">person:</span> </span><br><span class="line">  <span class="comment">#一个 - 代表一个JavaBean的数据</span></span><br><span class="line">  <span class="attr">pets:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">猫1</span></span><br><span class="line">      <span class="attr">weight:</span> <span class="number">99.99</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">猫2</span></span><br><span class="line">      <span class="attr">weight:</span> <span class="number">77.99</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>复杂的Map集合：Map&lt; String , List&lt; JavaBean &gt;&gt;</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#最前面加一个person，代表下面所有的变量将会加上person这个前缀</span></span><br><span class="line"><span class="attr">person:</span> </span><br><span class="line">  <span class="attr">allPets:</span></span><br><span class="line">    <span class="attr">sick:</span></span><br><span class="line">      <span class="comment">#写法方式一</span></span><br><span class="line">      <span class="bullet">-</span> &#123; <span class="attr">name:</span> <span class="string">生病的猫1</span>,<span class="attr">weight:</span> <span class="number">88.88</span> &#125;</span><br><span class="line">      <span class="comment">#写法方式二</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">生病的猫2</span></span><br><span class="line">        <span class="attr">weight:</span> <span class="number">989.89</span></span><br><span class="line">    <span class="attr">health:</span></span><br><span class="line">      <span class="bullet">-</span> &#123; <span class="attr">name:</span> <span class="string">健康的猫1</span>,<span class="attr">weight:</span> <span class="number">9999.9999</span> &#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
<h4 id="1-3、编写yaml配置文件提示问题"><a href="#1-3、编写yaml配置文件提示问题" class="headerlink" title="1.3、编写yaml配置文件提示问题"></a>1.3、编写yaml配置文件提示问题</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 编写yaml配置文件提示的包 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-configuration-processor<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">optional</span>&gt;</span>true<span class="tag">&lt;/<span class="name">optional</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--Maven打包插件--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">            <span class="comment">&lt;!--不打包：spring-boot-configuration-processor，编写配置文件提示--&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">proc</span>&gt;</span>none<span class="tag">&lt;/<span class="name">proc</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="1-4、注意"><a href="#1-4、注意" class="headerlink" title="1.4、注意"></a>1.4、注意</h4><p>==<strong>在yaml配置文件中编写的配置信息，在SpringBoot的properties配置文件中也能配置，如果两者对同一个属性同时进行配置，这时候SpringBoot的主配置文件application.properties配置文件中的会生效，约定大于配置</strong>==</p>
<p><strong>==properties文件和yaml文件的优先级：properties &gt; yaml文件==</strong></p>
<h2 id="二、web开发"><a href="#二、web开发" class="headerlink" title="二、web开发"></a>二、web开发</h2><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/web%E5%BC%80%E5%8F%91.webp" alt="web开发"></p>
<h3 id="1、SpringMVC自动配置概览"><a href="#1、SpringMVC自动配置概览" class="headerlink" title="1、SpringMVC自动配置概览"></a>1、SpringMVC自动配置概览</h3><p>Spring Boot provides auto-configuration for Spring MVC that <strong>works well with most applications.(大多场景我们都无需自定义配置)</strong></p>
<p>The auto-configuration adds the following features on top of Spring’s defaults:</p>
<ul>
<li><p>Inclusion of <code>ContentNegotiatingViewResolver</code> and <code>BeanNameViewResolver</code> beans.</p>
<ul>
<li>内容协商视图解析器和BeanName视图解析器</li>
</ul>
</li>
<li><p>Support for serving static resources, including support for WebJars (covered <a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-spring-mvc-static-content">later in this document</a>)).</p>
<ul>
<li>静态资源（包括webjars）</li>
</ul>
</li>
<li><p>Automatic registration of <code>Converter</code>, <code>GenericConverter</code>, and <code>Formatter</code> beans.</p>
<ul>
<li>自动注册 <code>Converter，GenericConverter，Formatter</code></li>
</ul>
</li>
<li><p>Support for <code>HttpMessageConverters</code> (covered <a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-spring-mvc-message-converters">later in this document</a>).</p>
<ul>
<li>支持 <code>HttpMessageConverters</code> （后来我们配合内容协商理解原理）</li>
</ul>
</li>
<li><p>Automatic registration of <code>MessageCodesResolver</code> (covered <a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-spring-message-codes">later in this document</a>).</p>
<ul>
<li>自动注册 <code>MessageCodesResolver</code> （国际化用）</li>
</ul>
</li>
<li><p>Static <code>index.html</code> support.</p>
<ul>
<li>静态index.html 页支持</li>
</ul>
</li>
<li><p>Custom <code>Favicon</code> support (covered <a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-spring-mvc-favicon">later in this document</a>).</p>
<ul>
<li>自定义 <code>Favicon</code>  </li>
</ul>
</li>
<li><p>Automatic use of a <code>ConfigurableWebBindingInitializer</code> bean (covered <a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-spring-mvc-web-binding-initializer">later in this document</a>).</p>
<ul>
<li>自动使用 <code>ConfigurableWebBindingInitializer</code> ，（DataBinder负责将请求数据绑定到JavaBean上）</li>
</ul>
</li>
</ul>
<blockquote>
<p>If you want to keep those Spring Boot MVC customizations and make more <a target="_blank" rel="noopener" href="https://docs.spring.io/spring/docs/5.2.9.RELEASE/spring-framework-reference/web.html#mvc">MVC customizations</a> (interceptors, formatters, view controllers, and other features), you can add your own <code>@Configuration</code> class of type <code>WebMvcConfigurer</code> but <strong>without</strong> <code>@EnableWebMvc</code>.</p>
<p><strong>不用@EnableWebMvc注解。使用</strong> <strong><code>@Configuration</code></strong> <strong>+</strong> <strong><code>WebMvcConfigurer</code></strong> <strong>自定义规则</strong></p>
<p>If you want to provide custom instances of <code>RequestMappingHandlerMapping</code>, <code>RequestMappingHandlerAdapter</code>, or <code>ExceptionHandlerExceptionResolver</code>, and still keep the Spring Boot MVC customizations, you can declare a bean of type <code>WebMvcRegistrations</code> and use it to provide custom instances of those components.</p>
<p><strong>声明</strong> <strong><code>WebMvcRegistrations</code></strong> <strong>改变默认底层组件</strong></p>
<p>If you want to take complete control of Spring MVC, you can add your own <code>@Configuration</code> annotated with <code>@EnableWebMvc</code>, or alternatively add your own <code>@Configuration</code>-annotated <code>DelegatingWebMvcConfiguration</code> as described in the Javadoc of <code>@EnableWebMvc</code>.</p>
<p><strong>使用</strong> <strong><code>@EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC</code></strong></p>
</blockquote>
<h3 id="2、简单功能分析"><a href="#2、简单功能分析" class="headerlink" title="2、简单功能分析"></a>2、简单功能分析</h3><h4 id="2-1、静态资源访问"><a href="#2-1、静态资源访问" class="headerlink" title="2.1、静态资源访问"></a>2.1、静态资源访问</h4><h5 id="2-1、静态资源默认目录"><a href="#2-1、静态资源默认目录" class="headerlink" title="2.1、静态资源默认目录"></a>2.1、静态资源默认目录</h5><p><strong>当静态资源的目录为默认目录的时候，此时静态只有放在默认路径的默认的几个文件夹下的静态资源才能访问的到</strong></p>
<blockquote>
<p>静态资源内容文档：</p>
<p><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-spring-mvc-static-content">https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-spring-mvc-static-content</a></p>
</blockquote>
<p>只要静态资源放在类路径下： ( <code>/static</code> or <code>/public</code> or <code>/resources</code> or <code>/META-INF/resources</code>)</p>
<p>访问 ： 当前项目根路径/ + 静态资源名 ，因为SpringBoot默认情况下，资源映射到/** ，但是您可以使用spring.mvc.static-path-pattern属性对其进行调整</p>
<p>例如，将所有资源重新定位到以下位置/resources/**可以实现：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">mvc:</span></span><br><span class="line">    <span class="attr">static-path-pattern:</span> <span class="string">/resources/**</span></span><br></pre></td></tr></table></figure>
<p>==<strong>此时如果静态资源的名字和请求的Conteroller路径名一样此时，SpringBoot会先去找Controller看能不能处理，不能处理的所有请求又都交给静态资源处理器。静态资源会去指定的目录下去寻找，如果静态资源也没有的话报404</strong>==</p>
<h5 id="2-2、静态资源访问前缀"><a href="#2-2、静态资源访问前缀" class="headerlink" title="2.2、静态资源访问前缀"></a>2.2、静态资源访问前缀</h5><p>SpringBoot默认访问静态资源是没有前缀的，默认为：当前项目根路径/ + 静态资源名</p>
<p>设置访问静态资源需要加上前缀</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">mvc:</span></span><br><span class="line">    <span class="attr">static-path-pattern:</span> <span class="string">/static/**</span></span><br><span class="line"><span class="comment">#此时访问静态资源的路径：当前项目根路径/ + static + 静态资源名</span></span><br></pre></td></tr></table></figure>
<p>==此时在配置文件中配置了访问静态资源需要加上前缀了，此时访问路径为：当前项目根路径/ + 前缀名 + 静态资源名==</p>
<h5 id="2-3、修改静态资源的默认目录"><a href="#2-3、修改静态资源的默认目录" class="headerlink" title="2.3、修改静态资源的默认目录"></a>2.3、修改静态资源的默认目录</h5><p>该</p>
<p>SpringBoot中默认的资源目录为，放在Maven的resource资源文件夹下面: ( <code>/static</code> or <code>/public</code> or <code>/resources</code> or <code>/META-INF/resources</code>)</p>
<p>==<strong>当四个目录下都有同样的资源时，优先级：resources &gt; static &gt; public &gt; /META-INF/resources</strong>==</p>
<p><strong>如果，在开发的时候不想文件放在SpringBoot指定的文件夹下面，此时可以使用<code>spring.web.resources.static-locations</code>来配置静态资源存放的目录，如果使用了<code>spring.web.resources.static-locations</code>来修改默认的目录，那么，此时默认的目录中存放的静态资源将不会被访问到，只有自己指定的目录下的资源文件才能被访问到</strong></p>
<ul>
<li><p>使用<code>spring.web.resources.static-locations</code></p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment">#设置静态资源存放的目录，可以配置多个目录</span></span><br><span class="line">  <span class="attr">web:</span></span><br><span class="line">    <span class="attr">resources:</span></span><br><span class="line">      <span class="attr">static-locations:</span> [ <span class="string">classpath:/myfile/</span>,<span class="string">classpath:/app/</span> ]</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="2-4、WebJars"><a href="#2-4、WebJars" class="headerlink" title="2.4、WebJars"></a>2.4、WebJars</h5><p>导入打包好的前端文件：<a target="_blank" rel="noopener" href="https://www.webjars.org/">https://www.webjars.org/</a></p>
<p>WebJars是将一些js文件打包成为了jar包，这些文件是存放在<code>webjars</code>文件夹下面的，此时访问路径为：==当前项目根路径/ + webjars + 静态资源名==</p>
<ul>
<li><p>在Maven中引入jQuery文件</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.webjars<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jquery<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.5.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>导入打包的jQuery之后访问：<a target="_blank" rel="noopener" href="http://localhost:8080/webjars/jquery/3.5.1/jquery.js">http://localhost:8080/webjars/jquery/3.5.1/jquery.js</a>   后面地址要按照依赖里面的包路径</p>
</li>
</ul>
<h4 id="2-2、欢迎页支持"><a href="#2-2、欢迎页支持" class="headerlink" title="2.2、欢迎页支持"></a>2.2、欢迎页支持</h4><p>Spring Boot支持静态和模板欢迎页面。它首先<code>index.html</code>在配置的静态内容位置中查找文件。如果找不到，它将寻找一个<code>index</code>模板。如果找到任何一个，它将自动用作应用程序的欢迎页面。</p>
<p><strong>欢迎页面就是在不加任何后缀就能访问到的页面。（例如：<a target="_blank" rel="noopener" href="http://localhost:8080/就会直接访问到index.html页面）">http://localhost:8080/就会直接访问到index.html页面）</a></strong></p>
<ul>
<li><p>静态资源路径下  index.html</p>
<ul>
<li>可以配置静态资源路径</li>
<li>但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问</li>
</ul>
</li>
<li><p>注意：如果配置了静态资源访问前缀则会失效</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line"><span class="comment">#  mvc:</span></span><br><span class="line"><span class="comment">#    static-path-pattern: /rel/**   这个会导致welcome page功能失效</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>controller能处理/index</p>
</li>
</ul>
<h4 id="2-3、自定义-Favicon"><a href="#2-3、自定义-Favicon" class="headerlink" title="2.3、自定义 Favicon"></a>2.3、自定义 Favicon</h4><p>favicon.ico 放在静态资源目录下即可。</p>
<h4 id="2-4、静态资源配置原理"><a href="#2-4、静态资源配置原理" class="headerlink" title="2,4、静态资源配置原理"></a>2,4、静态资源配置原理</h4><ul>
<li>SpringBoot启动默认加载  xxxAutoConfiguration 类（自动配置类）</li>
<li>SpringMVC功能的自动配置类 WebMvcAutoConfiguration，生效</li>
</ul>
<p><strong>==具体的配置需要去研究源码==</strong></p>
<h3 id="3、请求参数处理"><a href="#3、请求参数处理" class="headerlink" title="3、请求参数处理"></a>3、请求参数处理</h3><h4 id="3-1请求映射"><a href="#3-1请求映射" class="headerlink" title="3.1请求映射"></a>3.1请求映射</h4><h5 id="3-1-1、rest使用与原理"><a href="#3-1-1、rest使用与原理" class="headerlink" title="3.1.1、rest使用与原理"></a>3.1.1、rest使用与原理</h5><ul>
<li>@xxxMapping；<ul>
<li>@GetMapping、@DeleteMapping、@UpdateMapping、PostMapping、等</li>
</ul>
</li>
</ul>
<ul>
<li><p>Rest风格支持（使用<strong>HTTP</strong>请求方式动词来表示对资源的操作）</p>
<ul>
<li><p>以前：每个请求都要像一个映射名字，如：/getUser   获取用户     /deleteUser 删除用户    /editUser  修改用户       /saveUser 保存用户</p>
</li>
<li><p>现在：一个请求路径就可以处理四种请求方式 /user    GET-获取用户    DELETE-删除用户     PUT-修改用户      POST-保存用户</p>
</li>
<li><p>核心Filter；HiddenHttpMethodFilter</p>
<ul>
<li><p>用法： 表单method=post，写一个隐藏域（设置 name= _method，value=Get / Update / Delete / 其他）</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="meta">@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)</span></span><br><span class="line"><span class="meta">@ConditionalOnProperty(prefix = &quot;spring.mvc.hiddenmethod.filter&quot;, name = &quot;enabled&quot;, matchIfMissing = false)</span></span><br><span class="line"><span class="keyword">public</span> OrderedHiddenHttpMethodFilter <span class="title function_">hiddenHttpMethodFilter</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">OrderedHiddenHttpMethodFilter</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>扩展：如何把_method 这个名字换成我们自己喜欢的。写一个配置类，注册 HiddenHttpMethodFilter</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//自定义filter，想要将表单隐藏域中的_method改成其他的变量名，如_m、_myMethod、等</span></span><br><span class="line"><span class="comment">//此时可以使用自定义的HiddenHttpMethodFilter过滤器</span></span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> HiddenHttpMethodFilter <span class="title function_">hiddenHttpMethodFilter</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="type">HiddenHttpMethodFilter</span> <span class="variable">methodFilter</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HiddenHttpMethodFilter</span>();</span><br><span class="line">    methodFilter.setMethodParam(<span class="string">&quot;_m&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> methodFilter;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>SpringBoot中手动开启Rest功能</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">mvc:</span></span><br><span class="line">    <span class="attr">hiddenmethod:</span></span><br><span class="line">      <span class="attr">filter:</span></span><br><span class="line">        <span class="attr">enabled:</span> <span class="literal">true</span>   <span class="comment">#开启页面表单的Rest功能</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Rest原理（表单提交要使用REST的时候）</p>
<ul>
<li><p>使用表单请求一个Rest请求，表单method=post，写一个隐藏域（设置 name= _method，value=Get / Update / Delete / 其他）</p>
  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;/user&quot;</span> <span class="attr">method</span> = <span class="string">&quot;post&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 使用隐藏域来保存什么方式请求 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;hidden&quot;</span> <span class="attr">name</span>=<span class="string">&quot;_method&quot;</span> <span class="attr">value</span>=<span class="string">&quot;delete / get / update&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;点击提交一个delete的请求&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>表单提交会带上<strong>_method=PUT</strong></p>
</li>
<li><strong>请求过来会被</strong>HiddenHttpMethodFilter拦截<ul>
<li>请求是否正常，并且是POST<ul>
<li>获取到<strong>_method</strong>的值。</li>
<li>兼容以下请求；<strong>PUT</strong>.<strong>DELETE</strong>.<strong>PATCH</strong></li>
<li><strong>原生request（post），包装模式requesWrapper重写了getMethod方法，返回的是传入的值。</strong></li>
<li><strong>过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。</strong></li>
<li>HiddenHttpMethodFilter的具体作用：<a target="_blank" rel="noopener" href="https://blog.csdn.net/zhizhengguan/article/details/102975945">https://blog.csdn.net/zhizhengguan/article/details/102975945</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>Rest使用客户端工具，</strong></p>
<ul>
<li><p>如PostMan、ApiPost是直接发送Put、delete等方式请求，无需Filter。</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">mvc:</span></span><br><span class="line">    <span class="attr">hiddenmethod:</span></span><br><span class="line">      <span class="attr">filter:</span></span><br><span class="line">        <span class="attr">enabled:</span> <span class="literal">true</span>   <span class="comment">#开启页面表单的Rest功能</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="3-1-2、自定义Rest拦截器"><a href="#3-1-2、自定义Rest拦截器" class="headerlink" title="3.1.2、自定义Rest拦截器"></a>3.1.2、自定义Rest拦截器</h5><p><strong>当我们想把_method 这个名字换成我们自己喜欢的。此时可以写一个配置类，注册 HiddenHttpMethodFilter</strong></p>
<ul>
<li><p>注册一个<strong>HiddenHttpMethodFilter</strong></p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyConfig</span> &#123;</span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> HiddenHttpMethodFilter <span class="title function_">hiddenHttpMethodFilter</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">HiddenHttpMethodFilter</span> <span class="variable">filter</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HiddenHttpMethodFilter</span>();</span><br><span class="line">        <span class="comment">//配置自定义的隐藏域名字，不再使用_method作为参数来提交</span></span><br><span class="line">        filter.setMethodParam(<span class="string">&quot;_myMethod&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> filter;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>表单请求</p>
  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;/user&quot;</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;hidden&quot;</span> <span class="attr">name</span>=<span class="string">&quot;_myMethod&quot;</span> <span class="attr">value</span>=<span class="string">&quot;delete&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;点击发送一个delete请求&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>controller</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//delete请求写法一：</span></span><br><span class="line"><span class="comment">//@RequestMapping(value = &quot;/user&quot;, method = RequestMethod.DELETE)</span></span><br><span class="line"><span class="comment">//delete请求写法二：</span></span><br><span class="line"><span class="meta">@DeleteMapping(&quot;/user&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">deleteUser</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;DELETE-张三&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="3-1-3、请求映射原理"><a href="#3-1-3、请求映射原理" class="headerlink" title="3.1.3、请求映射原理"></a>3.1.3、请求映射原理</h5><p><strong>去研究源码</strong></p>
<h4 id="3-2、普通参数与基本注解"><a href="#3-2、普通参数与基本注解" class="headerlink" title="3.2、普通参数与基本注解"></a>3.2、普通参数与基本注解</h4><h5 id="3-2-1、注解"><a href="#3-2-1、注解" class="headerlink" title="3.2.1、注解"></a>3.2.1、注解</h5><p><strong>@PathVariable、@RequestHeader、@RequestParam、@CookieValue、@RequestBody、@RequestAttribute、@、@ModelAttribute、@MatrixVariable</strong></p>
<p><strong>==@requestBody这个标签在post 、put 方法中用于接收json格式的数据==</strong></p>
<p>&gt;<br>&gt;</p>
<blockquote>
<p><strong>@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的)；</strong></p>
<p><strong>GET方式无请求体，所以使用@RequestBody接收数据时，前端不能使用GET方式提交数据，而是用POST方式进行提交。在后端的同一个接收方法里，</strong></p>
<p><strong>@RequestBody与@RequestParam()可以同时使用，@RequestBody最多只能有一个，而@RequestParam()可以有多个。</strong></p>
<p><strong>注：一个请求，只有一个RequestBody；一个请求，可以有多个RequestParam。</strong></p>
</blockquote>
<ul>
<li><p>@PathVariable：获取Rest请求中的参数</p>
<ul>
<li><p>用法：【请求地址：/test1/1/张三 】</p>
<ul>
<li><p>获取指定的@PathVariable(“变量名”)，如果@PathVariable中没有指定属性名字，会根据绑定的参数的名字来寻找值，如果@PathVariable注解中传入了值，会根据值传入的名字来寻找对应的值</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/test1/&#123;id&#125;/&#123;name&#125;&quot;)</span></span><br><span class="line"><span class="keyword">public</span> Map&lt;String, Object&gt; <span class="title function_">test1</span><span class="params">(<span class="meta">@PathVariable</span> String id, <span class="meta">@PathVariable(&quot;name&quot;)</span> String name1)</span> &#123;  &#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>@PathVariable注解获取全部的值，不传入值，再绑定一个Map集合，此时会将全部的值封装为一个Map集合</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/test1/&#123;id&#125;/&#123;name&#125;&quot;)</span></span><br><span class="line"><span class="keyword">public</span> Map&lt;String, Object&gt; <span class="title function_">test1</span><span class="params">(<span class="meta">@PathVariable</span> Map&lt;String , Object&gt; map)</span> &#123;  &#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>@RequestHeader：获取请求头</p>
<ul>
<li><p>用法：</p>
<ul>
<li><p>获取指定的请求头：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> String <span class="title function_">test1</span><span class="params">(<span class="meta">@RequestHeader(&quot;Host&quot;)</span> String host)</span> &#123;    &#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>获取全部请求头：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> Map&lt;String, Object&gt; <span class="title function_">test1</span><span class="params">(<span class="meta">@RequestHeader</span> Map&lt;String, Object&gt; map)</span> &#123;    &#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>@RequestAttribute 和 @SessionAttribute</p>
<ul>
<li><p>用法：在使用这两个参数的时候最好传入一个属性：required = false，如果不将该属性的值设置为False，当取值的时候没有值会报错，而将该属性设置为false之后，就算没有存值取出来会是null，而不是报错</p>
<ul>
<li><p>存值</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/test1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">test1</span><span class="params">(HttpServletRequest request)</span> &#123;</span><br><span class="line">    request.getSession().setAttribute(<span class="string">&quot;password&quot;</span>, <span class="string">&quot;12345&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;forward:/req/test2&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>取值：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/test2&quot;)</span></span><br><span class="line"><span class="meta">@ResponseBody</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">test2</span><span class="params">(<span class="meta">@RequestAttribute(required = false)</span> String name,</span></span><br><span class="line"><span class="params">                    <span class="meta">@SessionAttribute(value = &quot;password&quot;, required = false)</span> Object password)</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;name = &quot;</span> + name + <span class="string">&quot; ===== password = &quot;</span> + password;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li>其他几个注解使用差不多，上网查找加参照使用</li>
</ul>
<h5 id="3-2-2、Servlet-API"><a href="#3-2-2、Servlet-API" class="headerlink" title="3.2.2、Servlet API"></a>3.2.2、Servlet API</h5><p>WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId</p>
<p><strong>ServletRequestMethodArgumentResolver  以上的部分参数</strong></p>
<pre><code>        <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">supportsParameter</span><span class="params">(MethodParameter parameter)</span> &#123;</span><br><span class="line">    Class&lt;?&gt; paramType = parameter.getParameterType();</span><br><span class="line">    <span class="keyword">return</span> (WebRequest.class.isAssignableFrom(paramType) ||</span><br><span class="line">            ServletRequest.class.isAssignableFrom(paramType) ||</span><br><span class="line">            MultipartRequest.class.isAssignableFrom(paramType) ||</span><br><span class="line">            HttpSession.class.isAssignableFrom(paramType) ||</span><br><span class="line">            (pushBuilder != <span class="literal">null</span> &amp;&amp; pushBuilder.isAssignableFrom(paramType)) ||</span><br><span class="line">            (Principal.class.isAssignableFrom(paramType) &amp;&amp; !parameter.hasParameterAnnotations()) ||</span><br><span class="line">            InputStream.class.isAssignableFrom(paramType) ||</span><br><span class="line">            Reader.class.isAssignableFrom(paramType) ||</span><br><span class="line">            HttpMethod.class == paramType ||</span><br><span class="line">            Locale.class == paramType ||</span><br><span class="line">            TimeZone.class == paramType ||</span><br><span class="line">            ZoneId.class == paramType);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</code></pre><h5 id="3-2-3、复杂参数"><a href="#3-2-3、复杂参数" class="headerlink" title="3.2.3、复杂参数"></a>3.2.3、复杂参数</h5><p><strong>Map</strong>、<strong>Model（map、model里面的数据会被放在request的请求域  request.setAttribute）、</strong>Errors/BindingResult、<strong>RedirectAttributes（ 重定向携带数据）</strong>、<strong>ServletResponse（response）</strong>、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Map&lt;String,Object&gt; map,  Model model, HttpServletRequest request 都是可以给request域中放数据，</span><br><span class="line">request.getAttribute();</span><br></pre></td></tr></table></figure>
<h5 id="3-2-4、自定义对象参数"><a href="#3-2-4、自定义对象参数" class="headerlink" title="3.2.4、自定义对象参数"></a>3.2.4、自定义对象参数</h5><p>可以自动类型转换与格式化，可以级联封装。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *     姓名： &lt;input name=&quot;userName&quot;/&gt; &lt;br/&gt;</span></span><br><span class="line"><span class="comment"> *     年龄： &lt;input name=&quot;age&quot;/&gt; &lt;br/&gt;</span></span><br><span class="line"><span class="comment"> *     生日： &lt;input name=&quot;birth&quot;/&gt; &lt;br/&gt;</span></span><br><span class="line"><span class="comment"> *     宠物姓名：&lt;input name=&quot;pet.name&quot;/&gt;&lt;br/&gt;</span></span><br><span class="line"><span class="comment"> *     宠物年龄：&lt;input name=&quot;pet.age&quot;/&gt;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">private</span> String userName;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> Date birth;</span><br><span class="line">    <span class="keyword">private</span> Pet pet;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Pet</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String age;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">result</span><br></pre></td></tr></table></figure>
<h4 id="3-3、POJO封装过程"><a href="#3-3、POJO封装过程" class="headerlink" title="3.3、POJO封装过程"></a>3.3、POJO封装过程</h4><ul>
<li><strong>研究源码：ServletModelAttributeMethodProcessor</strong></li>
</ul>
<h4 id="3-4、参数处理原理"><a href="#3-4、参数处理原理" class="headerlink" title="3.4、参数处理原理"></a>3.4、参数处理原理</h4><p>具体笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#6SNoJ">https://www.yuque.com/atguigu/springboot/vgzmgh#6SNoJ</a></p>
<h3 id="4、数据响应与内容协商"><a href="#4、数据响应与内容协商" class="headerlink" title="4、数据响应与内容协商"></a>4、数据响应与内容协商</h3><p>具体笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#ltqcb">https://www.yuque.com/atguigu/springboot/vgzmgh#ltqcb</a></p>
<h3 id="5、视图解析与模板引擎"><a href="#5、视图解析与模板引擎" class="headerlink" title="5、视图解析与模板引擎"></a>5、视图解析与模板引擎</h3><p><strong>视图解析：SpringBoot在处理完请求以后想要跳转到某个页面的过程，SpringBoot默认不支持JSP，需要引入第三方模板引擎技术实现页面渲染。</strong></p>
<h4 id="5-1、视图解析"><a href="#5-1、视图解析" class="headerlink" title="5.1、视图解析"></a>5.1、视图解析</h4><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90%E5%8E%9F%E7%90%86%E6%B5%81%E7%A8%8B.webp" alt="视图解析与原理流程"></p>
<h5 id="5-1-1、视图解析原理流程"><a href="#5-1-1、视图解析原理流程" class="headerlink" title="5.1.1、视图解析原理流程"></a>5.1.1、视图解析原理流程</h5><p>具体笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#ITRrl">https://www.yuque.com/atguigu/springboot/vgzmgh#ITRrl</a></p>
<h4 id="5-2、模板引擎-Thymeleaf"><a href="#5-2、模板引擎-Thymeleaf" class="headerlink" title="5.2、模板引擎-Thymeleaf"></a>5.2、模板引擎-Thymeleaf</h4><h5 id="5-2-1、Thymeleaf简介"><a href="#5-2-1、Thymeleaf简介" class="headerlink" title="5.2.1、Thymeleaf简介"></a>5.2.1、Thymeleaf简介</h5><p>Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text.</p>
<p><strong>Thymeleaf是一个现代化、服务端Java模板引擎</strong></p>
<h5 id="5-2-2、基本语法"><a href="#5-2-2、基本语法" class="headerlink" title="5.2.2、基本语法"></a>5.2.2、基本语法</h5><h6 id="5-2-1-1、表达式"><a href="#5-2-1-1、表达式" class="headerlink" title="5.2.1.1、表达式"></a>5.2.1.1、表达式</h6><div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">表达式名字</th>
<th style="text-align:center">语法</th>
<th style="text-align:center">用途</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">变量取值</td>
<td style="text-align:center">${…}</td>
<td style="text-align:center">获取请求域、session域、对象等值</td>
</tr>
<tr>
<td style="text-align:center">选择变量</td>
<td style="text-align:center">*{…}</td>
<td style="text-align:center">获取上下文对象值</td>
</tr>
<tr>
<td style="text-align:center">消息</td>
<td style="text-align:center">#{…}</td>
<td style="text-align:center">获取国际化等值</td>
</tr>
<tr>
<td style="text-align:center">链接</td>
<td style="text-align:center">@{…}</td>
<td style="text-align:center">生成链接</td>
</tr>
<tr>
<td style="text-align:center">片段表达式</td>
<td style="text-align:center">~{…}</td>
<td style="text-align:center">jsp:include 作用，引入公共页面片段</td>
</tr>
</tbody>
</table>
</div>
<h6 id="5-2-1-2、字面量"><a href="#5-2-1-2、字面量" class="headerlink" title="5.2.1.2、字面量"></a>5.2.1.2、字面量</h6><p>文本值: <strong>‘one text’</strong> <strong>,</strong> <strong>‘Another one!’</strong> <strong>,…</strong>数字: <strong>0</strong> <strong>,</strong> <strong>34</strong> <strong>,</strong> <strong>3.0</strong> <strong>,</strong> <strong>12.3</strong> <strong>,…</strong>布尔值: <strong>true</strong> <strong>,</strong> <strong>false</strong></p>
<p>空值: <strong>null</strong></p>
<p>变量： one，two，…. 变量不能有空格</p>
<h6 id="5-2-1-3、文本操作"><a href="#5-2-1-3、文本操作" class="headerlink" title="5.2.1.3、文本操作"></a>5.2.1.3、文本操作</h6><p>字符串拼接: <strong>+</strong></p>
<p>变量替换: <strong>|The name is ${name}|</strong> </p>
<h6 id="5-2-1-4、数学运算"><a href="#5-2-1-4、数学运算" class="headerlink" title="5.2.1.4、数学运算"></a>5.2.1.4、数学运算</h6><p>运算符: + , - , * , / , %</p>
<h6 id="5-2-1-5、布尔运算"><a href="#5-2-1-5、布尔运算" class="headerlink" title="5.2.1.5、布尔运算"></a>5.2.1.5、布尔运算</h6><p>运算符:  <strong>and</strong> <strong>,</strong> <strong>or</strong></p>
<p>一元运算: <strong>!</strong> <strong>,</strong> <strong>not</strong> </p>
<h6 id="5-2-1-6、比较运算"><a href="#5-2-1-6、比较运算" class="headerlink" title="5.2.1.6、比较运算"></a>5.2.1.6、比较运算</h6><p>比较: <strong>&gt;</strong> <strong>,</strong> <strong>&lt;</strong> <strong>,</strong> <strong>&gt;=</strong> <strong>,</strong> <strong>&lt;=</strong> <strong>(</strong> <strong>gt</strong> <strong>,</strong> <strong>lt</strong> <strong>,</strong> <strong>ge</strong> <strong>,</strong> <strong>le</strong> <strong>)</strong>等式: <strong>==</strong> <strong>,</strong> <strong>!=</strong> <strong>(</strong> <strong>eq</strong> <strong>,</strong> <strong>ne</strong> <strong>)</strong> </p>
<h6 id="5-2-1-7、条件运算"><a href="#5-2-1-7、条件运算" class="headerlink" title="5.2.1.7、条件运算"></a>5.2.1.7、条件运算</h6><p>If-then: <strong>(if) ? (then)</strong></p>
<p>If-then-else: <strong>(if) ? (then) : (else)</strong></p>
<p>Default: (value) <strong>?: (defaultvalue)</strong> </p>
<h6 id="5-2-1-8、特殊操作"><a href="#5-2-1-8、特殊操作" class="headerlink" title="5.2.1.8、特殊操作"></a>5.2.1.8、特殊操作</h6><p>无操作： _</p>
<h5 id="5-2-3、设置属性值-th-attr"><a href="#5-2-3、设置属性值-th-attr" class="headerlink" title="5.2.3、设置属性值-th:attr"></a>5.2.3、设置属性值-th:attr</h5><p>设置单个值</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;subscribe.html&quot;</span> <span class="attr">th:attr</span>=<span class="string">&quot;action=@&#123;/subscribe&#125;&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">fieldset</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;email&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Subscribe!&quot;</span> <span class="attr">th:attr</span>=<span class="string">&quot;value=#&#123;subscribe.submit&#125;&quot;</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">fieldset</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>设置多个值</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;../../images/gtvglogo.webp&quot;</span>  <span class="attr">th:attr</span>=<span class="string">&quot;src=@&#123;/images/gtvglogo.webp&#125;,title=#&#123;logo&#125;,alt=#&#123;logo&#125;&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<p>以上两个的代替写法 th:xxxx</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Subscribe!&quot;</span> <span class="attr">th:value</span>=<span class="string">&quot;#&#123;subscribe.submit&#125;&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;subscribe.html&quot;</span> <span class="attr">th:action</span>=<span class="string">&quot;@&#123;/subscribe&#125;&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>所有h5兼容的标签写法：<a target="_blank" rel="noopener" href="https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes">https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes</a></p>
<h5 id="5-2-4、迭代"><a href="#5-2-4、迭代" class="headerlink" title="5.2.4、迭代"></a>5.2.4、迭代</h5><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">tr</span> <span class="attr">th:each</span>=<span class="string">&quot;prod : $&#123;prods&#125;&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;prod.name&#125;&quot;</span>&gt;</span>Onions<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;prod.price&#125;&quot;</span>&gt;</span>2.41<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;prod.inStock&#125;? #&#123;true&#125; : #&#123;false&#125;&quot;</span>&gt;</span>yes<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">tr</span> <span class="attr">th:each</span>=<span class="string">&quot;prod,iterStat : $&#123;prods&#125;&quot;</span> <span class="attr">th:class</span>=<span class="string">&quot;$&#123;iterStat.odd&#125;? &#x27;odd&#x27;&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;prod.name&#125;&quot;</span>&gt;</span>Onions<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;prod.price&#125;&quot;</span>&gt;</span>2.41<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;prod.inStock&#125;? #&#123;true&#125; : #&#123;false&#125;&quot;</span>&gt;</span>yes<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="5-2-5、条件运算"><a href="#5-2-5、条件运算" class="headerlink" title="5.2.5、条件运算"></a>5.2.5、条件运算</h5><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;comments.html&quot;</span></span></span><br><span class="line"><span class="tag"><span class="attr">th:href</span>=<span class="string">&quot;@&#123;/product/comments(prodId=$&#123;prod.id&#125;)&#125;&quot;</span></span></span><br><span class="line"><span class="tag"><span class="attr">th:if</span>=<span class="string">&quot;$&#123;not #lists.isEmpty(prod.comments)&#125;&quot;</span>&gt;</span>view<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:switch</span>=<span class="string">&quot;$&#123;user.role&#125;&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span> <span class="attr">th:case</span>=<span class="string">&quot;&#x27;admin&#x27;&quot;</span>&gt;</span>User is an administrator<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span> <span class="attr">th:case</span>=<span class="string">&quot;#&#123;roles.manager&#125;&quot;</span>&gt;</span>User is a manager<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span> <span class="attr">th:case</span>=<span class="string">&quot;*&quot;</span>&gt;</span>User is some other thing<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="5-2-6、属性优先级"><a href="#5-2-6、属性优先级" class="headerlink" title="5.2.6、属性优先级"></a>5.2.6、属性优先级</h5><div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">Order</th>
<th style="text-align:center">Feature</th>
<th style="text-align:center">Attributes</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">1</td>
<td style="text-align:center">Fragment inclusion</td>
<td style="text-align:center"><code>th:include</code> <code>th:replace</code></td>
</tr>
<tr>
<td style="text-align:center">2</td>
<td style="text-align:center">Fragment iteration</td>
<td style="text-align:center"><code>th:each</code></td>
</tr>
<tr>
<td style="text-align:center">3</td>
<td style="text-align:center">Conditional evaluation</td>
<td style="text-align:center"><code>th:if</code> <code>th:unless</code> <code>th:switch</code> <code>th:case</code></td>
</tr>
<tr>
<td style="text-align:center">4</td>
<td style="text-align:center">Local variable definition</td>
<td style="text-align:center"><code>th:object</code> <code>th:with</code></td>
</tr>
<tr>
<td style="text-align:center">5</td>
<td style="text-align:center">General attribute modification</td>
<td style="text-align:center"><code>th:attr</code> <code>th:attrprepend</code> <code>th:attrappend</code></td>
</tr>
<tr>
<td style="text-align:center">6</td>
<td style="text-align:center">Specific attribute modification</td>
<td style="text-align:center"><code>th:value</code>, <code>th:href</code>, <code>th:src</code>, <code>...</code>.</td>
</tr>
<tr>
<td style="text-align:center">7</td>
<td style="text-align:center">Text (tag body modification)</td>
<td style="text-align:center"><code>th:text</code> <code>th:utext</code></td>
</tr>
<tr>
<td style="text-align:center">8</td>
<td style="text-align:center">Fragment specification</td>
<td style="text-align:center"><code>th:fragment</code></td>
</tr>
<tr>
<td style="text-align:center">9</td>
<td style="text-align:center">Fragment removal</td>
<td style="text-align:center"><code>th:remove</code></td>
</tr>
</tbody>
</table>
</div>
<h4 id="5-3、Thymeleaf使用"><a href="#5-3、Thymeleaf使用" class="headerlink" title="5.3、Thymeleaf使用"></a>5.3、Thymeleaf使用</h4><h5 id="5-3-1、引入Thymeleaf"><a href="#5-3-1、引入Thymeleaf" class="headerlink" title="5.3.1、引入Thymeleaf"></a>5.3.1、引入Thymeleaf</h5><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-thymeleaf<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="5-3-2、自动配置thymeleaf"><a href="#5-3-2、自动配置thymeleaf" class="headerlink" title="5.3.2、自动配置thymeleaf"></a>5.3.2、自动配置thymeleaf</h5><p><strong>在SpringBoot自动配置好了Thymeleaf，不需要自己再配置，直接使用</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration(proxyBeanMethods = false)</span></span><br><span class="line"><span class="meta">@EnableConfigurationProperties(ThymeleafProperties.class)</span></span><br><span class="line"><span class="meta">@ConditionalOnClass(&#123; TemplateMode.class, SpringTemplateEngine.class &#125;)</span></span><br><span class="line"><span class="meta">@AutoConfigureAfter(&#123; WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class &#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThymeleafAutoConfiguration</span> &#123; &#125;</span><br></pre></td></tr></table></figure>
<p>自动配好的策略</p>
<ul>
<li>1、所有thymeleaf的配置值都在 ThymeleafProperties</li>
<li>2、配置好了 <strong>SpringTemplateEngine</strong> </li>
<li><strong>3、配好了</strong> <strong>ThymeleafViewResolver</strong> </li>
<li>4、我们只需要直接开发页面</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//默认前缀，页面放到templates文件夹中</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">DEFAULT_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;classpath:/templates/&quot;</span>;</span><br><span class="line"><span class="comment">//所有的thymeleaf默认都都会跳转到一个  xxx.html</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">DEFAULT_SUFFIX</span> <span class="operator">=</span> <span class="string">&quot;.html&quot;</span>;  <span class="comment">//xxx.html</span></span><br></pre></td></tr></table></figure>
<h5 id="5-3-3、页面开发"><a href="#5-3-3、页面开发" class="headerlink" title="5.3.3、页面开发"></a>5.3.3、页面开发</h5><p>templates中的页面只能通过控制器跳转进入，不能直接访问到，static文件夹下的可以直接访问到</p>
<ul>
<li><p>控制器代码</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping(&quot;/toPage&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">toPage</span><span class="params">(Model model)</span> &#123;</span><br><span class="line">    <span class="comment">//Model中的数据会放到请求与中，相当于request.setAttribute(&quot;aa&quot;,aa)</span></span><br><span class="line">    model.addAttribute(<span class="string">&quot;msg&quot;</span>,<span class="string">&quot;存入的数据&quot;</span>);</span><br><span class="line">    model.addAttribute(<span class="string">&quot;url&quot;</span>,<span class="string">&quot;https://home.code-nav.cn/&quot;</span>);</span><br><span class="line">    <span class="comment">//由于Thymeleaf自动配置 了前缀和后缀，所以这里只需要输入文件的名称就行了</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;success&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>页面：<strong>需要再html标签中导入名称空间：xmlns:th=”<a target="_blank" rel="noopener" href="http://www.thymeleaf.org">http://www.thymeleaf.org</a>“</strong></p>
  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span> <span class="attr">xmlns:th</span>=<span class="string">&quot;http://www.thymeleaf.org&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">title</span>&gt;</span>Title<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--th:text：用来修改标签中的值--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">h1</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;msg&#125;&quot;</span>&gt;</span>哈哈<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 这里可以测试一下 $&#123;&#125; 和 @&#123;&#125; 取值的效果 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;$&#123;url&#125;&quot;</span>&gt;</span>去编程导航页面<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;url&#125;&quot;</span>&gt;</span>去编程导航页面2<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="5-4、构建后台管理系统"><a href="#5-4、构建后台管理系统" class="headerlink" title="5.4、构建后台管理系统"></a>5.4、构建后台管理系统</h4><h5 id="5-4-1、项目创建"><a href="#5-4-1、项目创建" class="headerlink" title="5.4.1、项目创建"></a>5.4.1、项目创建</h5><p>引入：thymeleaf、web-starter、devtools、lombok</p>
<h5 id="5-4-2、静态资源处理"><a href="#5-4-2、静态资源处理" class="headerlink" title="5.4.2、静态资源处理"></a>5.4.2、静态资源处理</h5><p>对于静态资源SpringBoot已经自动配置好了，只需要把所有静态资源放到 static 文件夹下</p>
<h5 id="5-4-3、路径构建"><a href="#5-4-3、路径构建" class="headerlink" title="5.4.3、路径构建"></a>5.4.3、路径构建</h5><p>th:action=”@{/login}”</p>
<h5 id="5-4-4、模板抽取"><a href="#5-4-4、模板抽取" class="headerlink" title="5.4.4、模板抽取"></a>5.4.4、模板抽取</h5><ul>
<li><code>th:insert</code> 如同插入的字面意思，将指定的代码片段插入主标签内</li>
<li><code>th:replace</code>如同替换的字面意思，将主标签替换为指定的代码片段</li>
<li><code>th:include</code> (3.0版本后已不推荐使用) 类似于th:insert, 不同的是在插入的时候不带代码片段的标签，只插入代码</li>
</ul>
<ul>
<li><p>公共部分：</p>
  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">footer</span> <span class="attr">th:fragment</span>=<span class="string">&quot;copy&quot;</span>&gt;</span></span><br><span class="line">   这是公共部分的值</span><br><span class="line"><span class="tag">&lt;/<span class="name">footer</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>三种引入方式：</p>
  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">th:insert</span>=<span class="string">&quot;footer :: copy&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">th:replace</span>=<span class="string">&quot;footer :: copy&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">th:include</span>=<span class="string">&quot;footer :: copy&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>三种引入方式的效果</p>
  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">footer</span>&gt;</span></span><br><span class="line">            这是公共部分的值</span><br><span class="line">        <span class="tag">&lt;/<span class="name">footer</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">footer</span>&gt;</span></span><br><span class="line">        这是公共部分的值</span><br><span class="line">    <span class="tag">&lt;/<span class="name">footer</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        这是公共部分的值</span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="5-4-5、页面跳转"><a href="#5-4-5、页面跳转" class="headerlink" title="5.4.5、页面跳转"></a>5.4.5、页面跳转</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping(&quot;/login&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">main</span><span class="params">(User user, HttpSession session, Model model)</span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(StringUtils.hasLength(user.getUserName()) &amp;&amp; <span class="string">&quot;123456&quot;</span>.equals(user.getPassword()))&#123;</span><br><span class="line">        <span class="comment">//把登陆成功的用户保存起来</span></span><br><span class="line">        session.setAttribute(<span class="string">&quot;loginUser&quot;</span>,user);</span><br><span class="line">        <span class="comment">//登录成功重定向到main.html;  重定向防止表单重复提交</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;redirect:/main.html&quot;</span>;</span><br><span class="line">    &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">        model.addAttribute(<span class="string">&quot;msg&quot;</span>,<span class="string">&quot;账号密码错误&quot;</span>);</span><br><span class="line">        <span class="comment">//回到登录页面</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;login&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h5 id="5-4-6、数据渲染"><a href="#5-4-6、数据渲染" class="headerlink" title="5.4.6、数据渲染"></a>5.4.6、数据渲染</h5><ul>
<li><p>后台传入数据</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping(&quot;/basic_table&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">basic_table</span><span class="params">(Model model)</span> &#123;</span><br><span class="line">    model.addAttribute(<span class="string">&quot;user&quot;</span>, Arrays.asList(</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;张三&quot;</span>, <span class="string">&quot;1&quot;</span>),</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;马尔扎哈&quot;</span>, <span class="string">&quot;2&quot;</span>),</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;李白&quot;</span>, <span class="string">&quot;3&quot;</span>),</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;韩信&quot;</span>, <span class="string">&quot;4&quot;</span>),</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;澜&quot;</span>, <span class="string">&quot;5&quot;</span>),</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;蔡文姬&quot;</span>, <span class="string">&quot;6&quot;</span>)</span><br><span class="line">    ));</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;table/basic_table&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>前端遍历数据 ：</p>
  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">table</span> <span class="attr">class</span>=<span class="string">&quot;display table table-bordered&quot;</span> <span class="attr">id</span>=<span class="string">&quot;hidden-table-info&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">thead</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">th</span>&gt;</span>#<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">th</span>&gt;</span>用户名<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">th</span>&gt;</span>密码<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">thead</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tbody</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tr</span> <span class="attr">class</span>=<span class="string">&quot;gradeX&quot;</span> <span class="attr">th:each</span>=<span class="string">&quot;user,stats:$&#123;users&#125;&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;stats.count&#125;&quot;</span>&gt;</span>Trident<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;user.userName&#125;&quot;</span>&gt;</span>Internet<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span> &gt;</span>[[$&#123;user.password&#125;]]<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tbody</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">table</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="6、拦截器"><a href="#6、拦截器" class="headerlink" title="6、拦截器"></a>6、拦截器</h3><p><strong>==配置了拦截器的执行顺序：preHandle（拦截器中的方法） ==&gt;&gt;   控制器中的方法  ==&gt;&gt;  postHandle（拦截器中的方法） ==&gt;&gt;  afterCompletion（拦截器中的方法） ==&gt;&gt;  可能会由于浏览器的原因会继续执行以前前面四步流程  ==&gt;&gt;  进入浏览器==</strong>    </p>
<h4 id="6-1、配置自定义拦截器"><a href="#6-1、配置自定义拦截器" class="headerlink" title="6.1、配置自定义拦截器"></a>6.1、配置自定义拦截器</h4><p><strong>实现HandlerInterceptor 接口</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LoginInterceptor</span> <span class="keyword">implements</span> <span class="title class_">HandlerInterceptor</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">preHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;1&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">requestURI</span> <span class="operator">=</span> request.getRequestURI();</span><br><span class="line">        log.info(<span class="string">&quot;preHandle拦截的请求路径是&#123;&#125;&quot;</span>, requestURI);</span><br><span class="line"></span><br><span class="line">        <span class="type">Object</span> <span class="variable">loginUser</span> <span class="operator">=</span> request.getSession().getAttribute(<span class="string">&quot;loginUser&quot;</span>);</span><br><span class="line">        <span class="keyword">if</span> (loginUser != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        request.setAttribute(<span class="string">&quot;msg&quot;</span>, <span class="string">&quot;请先登录&quot;</span>);</span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;/&quot;</span>).forward(request, response);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 目标方法执行完成以后</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">postHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;2&quot;</span>);</span><br><span class="line">        log.info(<span class="string">&quot;postHandle执行&#123;&#125;&quot;</span>, modelAndView);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 页面渲染以后</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterCompletion</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;3&quot;</span>);</span><br><span class="line">        log.info(<span class="string">&quot;afterCompletion执行异常&#123;&#125;&quot;</span>, ex);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="6-2、注册自定义拦截器"><a href="#6-2、注册自定义拦截器" class="headerlink" title="6.2、注册自定义拦截器"></a>6.2、注册自定义拦截器</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 1、编写一个拦截器实现HandlerInterceptor接口</span></span><br><span class="line"><span class="comment"> * 2、拦截器注册到容器中（实现WebMvcConfigurer的addInterceptors）</span></span><br><span class="line"><span class="comment"> * 3、指定拦截规则【如果是拦截所有，静态资源也会被拦截】</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AdminWebConfig</span> <span class="keyword">implements</span> <span class="title class_">WebMvcConfigurer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addInterceptors</span><span class="params">(InterceptorRegistry registry)</span> &#123;</span><br><span class="line">        registry.addInterceptor(<span class="keyword">new</span> <span class="title class_">LoginInterceptor</span>())</span><br><span class="line">            .addPathPatterns(<span class="string">&quot;/**&quot;</span>)  <span class="comment">//所有请求都被拦截包括静态资源</span></span><br><span class="line">            .excludePathPatterns(<span class="string">&quot;/&quot;</span>,<span class="string">&quot;/login&quot;</span>,<span class="string">&quot;/css/**&quot;</span>,<span class="string">&quot;/fonts/**&quot;</span>,<span class="string">&quot;/images/**&quot;</span>,<span class="string">&quot;/js/**&quot;</span>); <span class="comment">//放行的请求</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="6-3、拦截器原理"><a href="#6-3、拦截器原理" class="headerlink" title="6.3、拦截器原理"></a>6.3、拦截器原理</h4><p>1、根据当前请求，找到<strong>HandlerExecutionChain【</strong>可以处理请求的handler以及handler的所有 拦截器】</p>
<p>2、先来<strong>顺序执行</strong> 所有拦截器的 preHandle方法</p>
<ul>
<li>1、如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle</li>
<li>2、如果当前拦截器返回为false。直接   倒序执行所有已经执行了的拦截器的  afterCompletion；</li>
</ul>
<p><strong>3、如果任何一个拦截器返回false。直接跳出不执行目标方法</strong></p>
<p><strong>4、所有拦截器都返回True。执行目标方法</strong></p>
<p><strong>5、倒序执行所有拦截器的postHandle方法。</strong></p>
<p><strong>6、前面的步骤有任何异常都会直接倒序触发</strong> afterCompletion</p>
<p>7、页面成功渲染完成以后，也会倒序触发 afterCompletion</p>
<p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/%E6%8B%A6%E6%88%AA%E5%99%A8%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.webp" alt="拦截器执行流程"></p>
<h3 id="7、文件上传"><a href="#7、文件上传" class="headerlink" title="7、文件上传"></a>7、文件上传</h3><h4 id="1、表单页面"><a href="#1、表单页面" class="headerlink" title="1、表单页面"></a>1、表单页面</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span> <span class="attr">action</span>=<span class="string">&quot;/upload&quot;</span> <span class="attr">enctype</span>=<span class="string">&quot;multipart/form-data&quot;</span>&gt;</span> ....... <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="2、文件上传代码"><a href="#2、文件上传代码" class="headerlink" title="2、文件上传代码"></a>2、文件上传代码</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * MultipartFile自动封装上传过来的文件，如果是多文件上传，可以定义一个MultipartFile数组，SpringBoot会将文件封装成为一个数组</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@PostMapping(&quot;/upload&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">upload</span><span class="params">(<span class="meta">@RequestPart(&quot;photo&quot;)</span> MultipartFile photo,</span></span><br><span class="line"><span class="params">                     <span class="meta">@RequestPart(&quot;photos&quot;)</span> MultipartFile[] photos)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//将文件写入磁盘路径</span></span><br><span class="line">    <span class="keyword">if</span> (!photo.isEmpty()) &#123;</span><br><span class="line">        photo.transferTo(<span class="keyword">new</span> <span class="title class_">File</span>(realPath + photo.getOriginalFilename()));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//将文件写入磁盘路径</span></span><br><span class="line">    <span class="keyword">if</span> (photos.length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="comment">//多文件上传需要将上传的文件依次遍历存入磁盘中</span></span><br><span class="line">        <span class="keyword">for</span> (MultipartFile item : photos) &#123;</span><br><span class="line">            item.transferTo(<span class="keyword">new</span> <span class="title class_">File</span>(realPath + item.getOriginalFilename()));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;main&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3、修改文件上传配置文件"><a href="#3、修改文件上传配置文件" class="headerlink" title="3、修改文件上传配置文件"></a>3、修改文件上传配置文件</h4><p>再application.properties中修改文件上传的相关数据：</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#单个文件的大小设置</span></span><br><span class="line"><span class="attr">spring.servlet.multipart.max-file-size</span>=<span class="string">10MB</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#总共请求的文件的大小的设置，</span></span><br><span class="line"><span class="comment">#例如：当一次文件上传有单文件上传和多文件上传的时候，单文件上传中的文件的大小和多文件上传的文件的大小的总和 = 请求的大小</span></span><br><span class="line"><span class="attr">spring.servlet.multipart.max-request-size</span>=<span class="string">100MB</span></span><br></pre></td></tr></table></figure>
<h4 id="4、文件上传自动配置原理"><a href="#4、文件上传自动配置原理" class="headerlink" title="4、文件上传自动配置原理"></a>4、文件上传自动配置原理</h4><p><strong>文件上传自动配置原理笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#h9I1a">https://www.yuque.com/atguigu/springboot/vgzmgh#h9I1a</a></strong></p>
<h3 id="8、异常处理"><a href="#8、异常处理" class="headerlink" title="8、异常处理"></a>8、异常处理</h3><p><strong>笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#6ezTG">https://www.yuque.com/atguigu/springboot/vgzmgh#6ezTG</a></strong></p>
<p><strong>想要配置错误页面，需要再template文件夹下设置一个error文件夹，专门用来放错误页面，页面中放的文件的 名字就会是错误信息的状态码，例如：想要配置一个404错误的页面，只需要在template文件夹下面的error文件夹中写一个404.html文件就行了，当发生404错误的时候就会自动跳转到404页面，例如：写一个5xx.html的文件，只要出现以5开头的错误的状态码都会跳转到5xx.html页面中</strong></p>
<h4 id="8-1、错误处理"><a href="#8-1、错误处理" class="headerlink" title="8.1、错误处理"></a>8.1、错误处理</h4><h5 id="8-1-1、默认规则"><a href="#8-1-1、默认规则" class="headerlink" title="8.1.1、默认规则"></a>8.1.1、默认规则</h5><ul>
<li>默认情况下，Spring Boot提供<code>/error</code>处理所有错误的映射</li>
<li>对于机器客户端，它将生成JSON响应，其中包含错误，HTTP状态和异常消息的详细信息。对于浏览器客户端，响应一个“ whitelabel”错误视图，以HTML格式呈现相同的数据</li>
</ul>
<h5 id="8-1-2、定制错误处理逻辑"><a href="#8-1-2、定制错误处理逻辑" class="headerlink" title="8.1.2、定制错误处理逻辑"></a>8.1.2、定制错误处理逻辑</h5><h5 id="8-1-3、异常处理自动配置原理"><a href="#8-1-3、异常处理自动配置原理" class="headerlink" title="8.1.3、异常处理自动配置原理"></a>8.1.3、异常处理自动配置原理</h5><h5 id="8-1-4、异常处理步骤流程"><a href="#8-1-4、异常处理步骤流程" class="headerlink" title="8.1.4、异常处理步骤流程"></a>8.1.4、异常处理步骤流程</h5><h3 id="9、Web原生组件注入（Servlet、Filter、Listener）"><a href="#9、Web原生组件注入（Servlet、Filter、Listener）" class="headerlink" title="9、Web原生组件注入（Servlet、Filter、Listener）"></a>9、Web原生组件注入（Servlet、Filter、Listener）</h3><p>==<strong>如果想要将Servlet、Filter、Listener都能在SpringBoot中使用，需要在SpringBoot的启动类中使用@ServletComponentScan注解来扫描进去</strong>==</p>
<h4 id="9-1、使用Servlet-API"><a href="#9-1、使用Servlet-API" class="headerlink" title="9.1、使用Servlet API"></a>9.1、使用Servlet API</h4><ul>
<li>注册Servlet三大组件<ul>
<li>@ServletComponentScan(basePackages = <strong>“com.atguigu.admin”</strong>) :指定原生Servlet组件都放在那里</li>
</ul>
</li>
<li>注册Serlvet三大组件<ul>
<li>@WebServlet(urlPatterns = <strong>“/my”</strong>)：效果：直接响应，<strong>没有经过Spring的拦截器？</strong></li>
<li>@WebFilter(urlPatterns={<strong>“/css/*“</strong>,<strong>“/images/*“</strong>})</li>
<li>@WebListener</li>
</ul>
</li>
</ul>
<p>​    </p>
<h4 id="9-2、使用-ServletComponentScan注册Servlet组件"><a href="#9-2、使用-ServletComponentScan注册Servlet组件" class="headerlink" title="9.2、使用@ServletComponentScan注册Servlet组件"></a>9.2、使用@ServletComponentScan注册Servlet组件</h4><blockquote>
<p><strong>使用@ServletComponentScan扫描Servlet组件</strong></p>
</blockquote>
<ul>
<li><p>假如三大组件都放在：con.lf.servlet这个包下，使用@ServletComponentScan扫描Servlet三大组件</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//想要将自己写的Servlet能被访问到，需要在SpringBoot的启动类中加上：@ServletComponentScan，传入Servlet组件的路径</span></span><br><span class="line"><span class="meta">@ServletComponentScan(basePackages = &quot;com.lf.servlet&quot;)</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Springboot03WebAdminApplication</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(Springboot03WebAdminApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>@WebServlet：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//编写一个类继承HttpServlet类</span></span><br><span class="line"><span class="meta">@WebServlet(urlPatterns = &quot;/my&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyServlet</span> <span class="keyword">extends</span> <span class="title class_">HttpServlet</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doGet</span><span class="params">(HttpServletRequest req, HttpServletResponse resp)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        resp.getWriter().write(<span class="string">&quot;这是原生继承HttpServlet的方法&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>@WebFilter</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@WebFilter(filterName = &quot;MyFilter&quot;,urlPatterns = &#123;&quot;/css/*,&quot;&#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyFilter</span> <span class="keyword">implements</span> <span class="title class_">Filter</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">init</span><span class="params">(FilterConfig config)</span> <span class="keyword">throws</span> ServletException &#123;</span><br><span class="line">        log.info(<span class="string">&quot;Filter初始化&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">destroy</span><span class="params">()</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;Filter销毁&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doFilter</span><span class="params">(ServletRequest request, ServletResponse response, FilterChain chain)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        log.info(<span class="string">&quot;Filter工作&quot;</span>);</span><br><span class="line">        chain.doFilter(request, response);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>WebListener</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="comment">//@WebListener</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MySwervletContextListener</span> <span class="keyword">implements</span> <span class="title class_">ServletContextListener</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">contextInitialized</span><span class="params">(ServletContextEvent sce)</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;MySwervletContextListener监听到项目初始化完成&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">contextDestroyed</span><span class="params">(ServletContextEvent sce)</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;MySwervletContextListener监听到项目销毁&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="9-3、使用RegistrationBean注册Servlet组件"><a href="#9-3、使用RegistrationBean注册Servlet组件" class="headerlink" title="9.3、使用RegistrationBean注册Servlet组件"></a>9.3、使用RegistrationBean注册Servlet组件</h4><p>ServletRegistrationBean<T extends Servlet>：注册Servlet</p>
<p>FilterRegistrationBean<T extends Filter>：注册Filter</p>
<p>ServletListenerRegistrationBean<T extends EventListener>：注册Listener</p>
<ul>
<li><p>写好三大组件：不需要在组件上写@WebServlet、@WebFilter、@WebListener，只需要写一个类实现或者继承对应的接口或者类就行了</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyServlet</span> <span class="keyword">extends</span> <span class="title class_">HttpServlet</span> &#123;  &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyFilter</span> <span class="keyword">implements</span> <span class="title class_">Filter</span> &#123; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MySwervletContextListener</span> <span class="keyword">implements</span> <span class="title class_">ServletContextListener</span> &#123;  &#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>写一个配置类，将组件注册：</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyRegisterConfig</span> &#123;</span><br><span class="line">    <span class="comment">//注册Servlet</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> ServletRegistrationBean&lt;MyServlet&gt; <span class="title function_">servletRegister</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ServletRegistrationBean</span>&lt;&gt;(<span class="keyword">new</span> <span class="title class_">MyServlet</span>(), <span class="string">&quot;/my&quot;</span>, <span class="string">&quot;/my2&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//注册Filter</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> FilterRegistrationBean&lt;MyFilter&gt; <span class="title function_">filterRegister</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//可以在创建FilterRegistrationBean的时候往构造函数中传入一个ServletRegistrationBean，这时候就会只拦截该servlet</span></span><br><span class="line">        FilterRegistrationBean&lt;MyFilter&gt; registrationBean2 = </span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">FilterRegistrationBean</span>&lt;&gt;(<span class="keyword">new</span> <span class="title class_">MyFilter</span>(),servletRegister());</span><br><span class="line">        </span><br><span class="line">        FilterRegistrationBean&lt;MyFilter&gt; registrationBean = <span class="keyword">new</span> <span class="title class_">FilterRegistrationBean</span>&lt;&gt;(<span class="keyword">new</span> <span class="title class_">MyFilter</span>());</span><br><span class="line">        <span class="comment">//拦截规则1：传入一个集合，集合中存的是拦截规则</span></span><br><span class="line">        registrationBean.setUrlPatterns(Arrays.asList(<span class="string">&quot;/css/*&quot;</span>, <span class="string">&quot;/js/*&quot;</span>));</span><br><span class="line">        <span class="keyword">return</span> registrationBean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//注册Listener</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> ServletListenerRegistrationBean&lt;MyListener&gt; <span class="title function_">listenerRegister</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ServletListenerRegistrationBean</span>&lt;MyListener&gt;(<span class="keyword">new</span> <span class="title class_">MyListener</span>());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="10、嵌入式Servlet容器"><a href="#10、嵌入式Servlet容器" class="headerlink" title="10、嵌入式Servlet容器"></a>10、嵌入式Servlet容器</h3><p><strong>笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#ED2gi">https://www.yuque.com/atguigu/springboot/vgzmgh#ED2gi</a></strong></p>
<h4 id="11、定制化原理"><a href="#11、定制化原理" class="headerlink" title="11、定制化原理"></a>11、定制化原理</h4><p><strong>笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#cQant">https://www.yuque.com/atguigu/springboot/vgzmgh#cQant</a></strong></p>
<p><strong>本章可以全面接管SpringMVC，比如，静态资源过滤，视图解析器，等等都需要自己写，没有把握别使用。还可增加心功能，修改旧功能，替代原有的自动化配置好的组件等</strong></p>
<p>&gt;<br>&gt;</p>
<blockquote>
<p><strong>一般想要定制一些SpringBoot配置好的，只需要写一个配置类实现WebMvcConfigurer即可定义web功能，然后使用@Bean注解往SpringBoot添加扩展一些新的功能，没有必要全面接管SpringMVC来全部自定义配置</strong></p>
</blockquote>
<h5 id="11-1、定制化的常见方式"><a href="#11-1、定制化的常见方式" class="headerlink" title="11.1、定制化的常见方式"></a>11.1、定制化的常见方式</h5><p><strong>笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#eSDgT">https://www.yuque.com/atguigu/springboot/vgzmgh#eSDgT</a></strong></p>
<h5 id="11-2、原理分析"><a href="#11-2、原理分析" class="headerlink" title="11.2、原理分析"></a>11.2、原理分析</h5><p><strong>笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/vgzmgh#GH9jB">https://www.yuque.com/atguigu/springboot/vgzmgh#GH9jB</a></strong></p>
<h2 id="三、数据访问（操作数据库）"><a href="#三、数据访问（操作数据库）" class="headerlink" title="三、数据访问（操作数据库）"></a>三、数据访问（操作数据库）</h2><h3 id="1、SQL"><a href="#1、SQL" class="headerlink" title="1、SQL"></a>1、SQL</h3><h4 id="1-1、数据源的自动配置-HikariDataSource"><a href="#1-1、数据源的自动配置-HikariDataSource" class="headerlink" title="1.1、数据源的自动配置-HikariDataSource"></a>1.1、数据源的自动配置-HikariDataSource</h4><h5 id="1-1-1、导入JDBC场景"><a href="#1-1-1、导入JDBC场景" class="headerlink" title="1.1.1、导入JDBC场景"></a>1.1.1、导入JDBC场景</h5><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-data-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/JDBC%E5%9C%BA%E6%99%AF.webp" alt="JDBC场景"></p>
<p>通过上图可以看到没有数据库驱动，因为官方不知道我们使用的是什么数据库，MySQL、Oracle</p>
<p>还有就是数据库驱动的版本和我们装的数据库版本是否一致等问题，这时需要我们自己导入数据库连接驱动</p>
<ul>
<li><p>MySQL的数据库连接驱动</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--当SpringBoot提供的版本和装的版本一致的时候可以不需要写版本。--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>8.0.19<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="1-1-2、分析自动配置"><a href="#1-1-2、分析自动配置" class="headerlink" title="1.1.2、分析自动配置"></a>1.1.2、分析自动配置</h5><h6 id="1、自动配置的类"><a href="#1、自动配置的类" class="headerlink" title="1、自动配置的类"></a>1、自动配置的类</h6><ul>
<li><p>DataSourceAutoConfiguration ： 数据源的自动配置</p>
<ul>
<li>修改数据源相关的配置：<strong>spring.datasource</strong></li>
<li><strong>数据库连接池的配置，是自己容器中没有DataSource才自动配置的</strong></li>
<li><p>底层配置好的连接池是：<strong>HikariDataSource</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration(proxyBeanMethods = false)</span></span><br><span class="line"><span class="meta">@Conditional(PooledDataSourceCondition.class)</span></span><br><span class="line"><span class="meta">@ConditionalOnMissingBean(&#123; DataSource.class, XADataSource.class &#125;)</span></span><br><span class="line"><span class="meta">@Import(&#123; DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,</span></span><br><span class="line"><span class="meta">         DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,</span></span><br><span class="line"><span class="meta">         DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class &#125;)</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">PooledDataSourceConfiguration</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
<li><p>DataSourceTransactionManagerAutoConfiguration： 事务管理器的自动配置</p>
</li>
<li><p>JdbcTemplateAutoConfiguration： <strong>JdbcTemplate的自动配置，可以来对数据库进行crud</strong></p>
<ul>
<li>可以修改这个配置项@ConfigurationProperties(prefix = <strong>“spring.jdbc”</strong>) 来修改JdbcTemplate</li>
<li>@Bean@Primary   JdbcTemplate；容器中有这个组件</li>
</ul>
</li>
<li><p>JndiDataSourceAutoConfiguration： jndi的自动配置</p>
</li>
<li>XADataSourceAutoConfiguration： 分布式事务相关的</li>
</ul>
<h5 id="3-1-3、修改配置项"><a href="#3-1-3、修改配置项" class="headerlink" title="3.1.3、修改配置项"></a>3.1.3、修改配置项</h5><p>修改连接地址，驱动地址，用户名和密码等信息</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/db_account</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="number">123456</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.jdbc.Driver</span></span><br></pre></td></tr></table></figure>
<h5 id="3-1-4、测试"><a href="#3-1-4、测试" class="headerlink" title="3.1.4、测试"></a>3.1.4、测试</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SpringbootDataApplicationTests</span> &#123;</span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> JdbcTemplate jdbcTemplate;</span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">contextLoads</span><span class="params">()</span> &#123;</span><br><span class="line">        jdbcTemplate.queryForList(<span class="string">&quot;select *from employee&quot;</span>).forEach(System.out::println);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="1-2、使用Druid数据源"><a href="#1-2、使用Druid数据源" class="headerlink" title="1.2、使用Druid数据源"></a>1.2、使用Druid数据源</h4><h5 id="1-2-1、Druid的GitHub地址"><a href="#1-2-1、Druid的GitHub地址" class="headerlink" title="1.2.1、Druid的GitHub地址"></a>1.2.1、Druid的GitHub地址</h5><p><a target="_blank" rel="noopener" href="https://github.com/alibaba/druid">https://github.com/alibaba/druid</a></p>
<h5 id="1-2-2、SpringBoot整合Druid"><a href="#1-2-2、SpringBoot整合Druid" class="headerlink" title="1.2.2、SpringBoot整合Druid"></a>1.2.2、SpringBoot整合Druid</h5><p>SpringBoot整合第三方技术的两种方式</p>
<ul>
<li>自定义</li>
<li>找status</li>
</ul>
<h5 id="1-2-3、自定义方式"><a href="#1-2-3、自定义方式" class="headerlink" title="1.2.3、自定义方式"></a>1.2.3、自定义方式</h5><h6 id="1-2-3-1、创建数据源"><a href="#1-2-3-1、创建数据源" class="headerlink" title="1.2.3.1、创建数据源"></a>1.2.3.1、创建数据源</h6><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>druid<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.1.17<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h6 id="1-2-3-2、StatViewServlet"><a href="#1-2-3-2、StatViewServlet" class="headerlink" title="1.2.3.2、StatViewServlet"></a>1.2.3.2、StatViewServlet</h6><p>StatViewServlet的用途包括：</p>
<ul>
<li>提供监控信息展示的html页面</li>
<li>提供监控信息的JSON API</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 配置 druid的监控页功能</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> ServletRegistrationBean <span class="title function_">statViewServlet</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="type">StatViewServlet</span> <span class="variable">statViewServlet</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StatViewServlet</span>();</span><br><span class="line">    ServletRegistrationBean&lt;StatViewServlet&gt; registrationBean = <span class="keyword">new</span> <span class="title class_">ServletRegistrationBean</span>&lt;&gt;(statViewServlet, <span class="string">&quot;/druid/*&quot;</span>);</span><br><span class="line"></span><br><span class="line">    registrationBean.addInitParameter(<span class="string">&quot;loginUsername&quot;</span>,<span class="string">&quot;admin&quot;</span>);</span><br><span class="line">    registrationBean.addInitParameter(<span class="string">&quot;loginPassword&quot;</span>,<span class="string">&quot;123456&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> registrationBean;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h6 id="1-2-3-3、StatFilter"><a href="#1-2-3-3、StatFilter" class="headerlink" title="1.2.3.3、StatFilter"></a>1.2.3.3、StatFilter</h6><p>用于统计监控信息；如SQL监控、URI监控</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * WebStatFilter 用于采集web-jdbc关联监控的数据。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> FilterRegistrationBean <span class="title function_">webStatFilter</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="type">WebStatFilter</span> <span class="variable">webStatFilter</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">WebStatFilter</span>();</span><br><span class="line"></span><br><span class="line">    FilterRegistrationBean&lt;WebStatFilter&gt; filterRegistrationBean = <span class="keyword">new</span> <span class="title class_">FilterRegistrationBean</span>&lt;&gt;(webStatFilter);</span><br><span class="line">    filterRegistrationBean.setUrlPatterns(Arrays.asList(<span class="string">&quot;/*&quot;</span>));</span><br><span class="line">    filterRegistrationBean.addInitParameter(<span class="string">&quot;exclusions&quot;</span>,<span class="string">&quot;*.js,*.gif,*.webp,*.webp,*.css,*.ico,/druid/*&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> filterRegistrationBean;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h5 id="1-2-4、使用官方starter方式"><a href="#1-2-4、使用官方starter方式" class="headerlink" title="1.2.4、使用官方starter方式"></a>1.2.4、使用官方starter方式</h5><p><strong>官网地址：<a target="_blank" rel="noopener" href="https://hub.fastgit.org/alibaba/druid/tree/master/druid-spring-boot-starter">https://hub.fastgit.org/alibaba/druid/tree/master/druid-spring-boot-starter</a></strong></p>
<h6 id="1-2-4-1、引入druid-stater"><a href="#1-2-4-1、引入druid-stater" class="headerlink" title="1.2.4.1、引入druid-stater"></a>1.2.4.1、引入druid-stater</h6><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>druid-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.1.17<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h6 id="1-2-4-2、分析自动配置"><a href="#1-2-4-2、分析自动配置" class="headerlink" title="1.2.4.2、分析自动配置"></a>1.2.4.2、分析自动配置</h6><ul>
<li><p>扩展配置项 <strong>spring.datasource.druid</strong></p>
</li>
<li><p>DruidSpringAopConfiguration.<strong>class</strong>,  监控SpringBean的；配置项：<strong>spring.datasource.druid.aop-patterns</strong></p>
</li>
<li><p>DruidStatViewServletConfiguration.<strong>class</strong>, 监控页的配置：<strong>spring.datasource.druid.stat-view-servlet；默认开启</strong></p>
</li>
<li><p>DruidWebStatFilterConfiguration.<strong>class</strong>, web监控配置；<strong>spring.datasource.druid.web-stat-filter；默认开启</strong></p>
</li>
<li><p>DruidFilterConfiguration.<strong>class</strong>}) 所有Druid自己filter的配置</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILTER_STAT_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;spring.datasource.druid.filter.stat&quot;</span>;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILTER_CONFIG_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;spring.datasource.druid.filter.config&quot;</span>;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILTER_ENCODING_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;spring.datasource.druid.filter.encoding&quot;</span>;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILTER_SLF4J_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;spring.datasource.druid.filter.slf4j&quot;</span>;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILTER_LOG4J_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;spring.datasource.druid.filter.log4j&quot;</span>;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILTER_LOG4J2_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;spring.datasource.druid.filter.log4j2&quot;</span>;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILTER_COMMONS_LOG_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;spring.datasource.druid.filter.commons-log&quot;</span>;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILTER_WALL_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;spring.datasource.druid.filter.wall&quot;</span>;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h6 id="1-2-4-3、配置示例"><a href="#1-2-4-3、配置示例" class="headerlink" title="1.2.4.3、配置示例"></a>1.2.4.3、配置示例</h6><p><strong>只需要将下面代码设置后，就可以直接使用Druid的监控页面了，访问路径为：<a target="_blank" rel="noopener" href="http://localhost:8080/druid/">http://localhost:8080/druid/</a></strong></p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">druid:</span></span><br><span class="line">      <span class="attr">aop-patterns:</span> <span class="string">com.lf.*</span>  <span class="comment">#springbean监控</span></span><br><span class="line">      <span class="attr">filters:</span> <span class="string">stat,wall,slf4j</span>  <span class="comment">#所有开启的功能</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">stat-view-servlet:</span> <span class="comment">#监控页配置</span></span><br><span class="line">        <span class="attr">enabled:</span> <span class="literal">true</span>  <span class="comment">#设置开启监控页，监控页默认关闭</span></span><br><span class="line">        <span class="attr">login-username:</span> <span class="string">admin</span> <span class="comment">#进入监控页账号</span></span><br><span class="line">        <span class="attr">login-password:</span> <span class="string">admin</span> <span class="comment">#进入监控页密码</span></span><br><span class="line">        <span class="attr">resetEnable:</span> <span class="literal">false</span> <span class="comment">#设置重置按钮是否有效</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">web-stat-filter:</span> <span class="comment">#web监控</span></span><br><span class="line">        <span class="attr">enabled:</span> <span class="literal">true</span> <span class="comment">#设置开启web监控，web监控默认关闭</span></span><br><span class="line">        <span class="attr">urlPattern:</span> <span class="string">/*</span>  <span class="comment">#监控路径配置</span></span><br><span class="line">        <span class="attr">exclusions:</span> <span class="string">&#x27;*.js,*.gif,*.webp,*.webp,*.css,*.ico,/druid/*&#x27;</span> <span class="comment">#设置排除哪些，该选项有默认值，可以不填</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">filter:</span></span><br><span class="line">        <span class="attr">stat:</span> <span class="comment">#sql监控</span></span><br><span class="line">          <span class="attr">enabled:</span> <span class="literal">true</span> <span class="comment">#设置开启sql监控，sql监控默认关闭</span></span><br><span class="line">          <span class="attr">slow-sql-millis:</span> <span class="number">1000</span> <span class="comment">#配置超过1000毫秒的都是慢SQL</span></span><br><span class="line">          <span class="attr">logSlowSql:</span> <span class="literal">true</span> <span class="comment">#是否记录慢SQL</span></span><br><span class="line">        <span class="attr">wall:</span> <span class="comment">#防火墙</span></span><br><span class="line">          <span class="attr">enabled:</span> <span class="literal">true</span> <span class="comment">#设置开启防火墙，防火墙默认关闭</span></span><br><span class="line">          <span class="attr">config:</span></span><br><span class="line">            <span class="string">drop@-table-allow:</span> <span class="literal">false</span> <span class="comment">#设置是否允许删除表</span></span><br></pre></td></tr></table></figure>
<h4 id="1-3、整合MyBatis"><a href="#1-3、整合MyBatis" class="headerlink" title="1.3、整合MyBatis"></a>1.3、整合MyBatis</h4><p><strong>镜像官网：<a target="_blank" rel="noopener" href="https://hub.fastgit.org/mybatis">https://hub.fastgit.org/mybatis</a></strong></p>
<p><strong>官网：<a target="_blank" rel="noopener" href="https://github.com/mybatis">https://github.com/mybatis</a></strong></p>
<ul>
<li><p>引入MyBatis的starter</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.4<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h5 id="1-3-1、配置模式"><a href="#1-3-1、配置模式" class="headerlink" title="1.3.1、配置模式"></a>1.3.1、配置模式</h5><ul>
<li><p>全局配置文件</p>
</li>
<li><p>SqlSessionFactory: 自动配置好了</p>
</li>
<li><p>SqlSession：自动配置了 <strong>SqlSessionTemplate 组合了SqlSession</strong></p>
</li>
<li><p>@Import(<strong>AutoConfiguredMapperScannerRegistrar</strong>.<strong>class</strong>）；</p>
</li>
<li><p>Mapper： 只要我们写的操作MyBatis的接口标注了 <strong>@Mapper 就会被自动扫描进来</strong></p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableConfigurationProperties(MybatisProperties.class)</span></span><br><span class="line"><span class="meta">@AutoConfigureAfter(&#123; DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class &#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MybatisAutoConfiguration</span> <span class="keyword">implements</span> <span class="title class_">InitializingBean</span> &#123;   &#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<blockquote>
<p>可以修改配置文件中 以mybatis开始修改mybatis的配置：</p>
</blockquote>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 配置mybatis规则</span></span><br><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="attr">config-location:</span> <span class="string">classpath:mybatis/mybatis-config.xml</span>  <span class="comment">#全局配置文件位置</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath:mybatis/mapper/*.xml</span>  <span class="comment">#sql映射文件位置</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>mybatis-config：</p>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Mapper接口---&gt;绑定Xml</span><br><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;com.atguigu.admin.mapper.AccountMapper&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--    public Account getAcct(Long id); --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getAcct&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;com.atguigu.admin.bean.Account&quot;</span>&gt;</span></span><br><span class="line">        select * from  account_tbl where  id=#&#123;id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>配置 <strong>private</strong> Configuration <strong>configuration</strong>; mybatis.<strong>configuration下面的所有，就是相当于改mybatis全局配置文件中的值</strong></p>
</blockquote>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 配置mybatis规则</span></span><br><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="comment">#config-location: classpath:mybatis/mybatis-config.xml</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath:mybatis/mapper/*.xml</span></span><br><span class="line">  <span class="attr">configuration:</span></span><br><span class="line">    <span class="attr">map-underscore-to-camel-case:</span> <span class="literal">true</span></span><br><span class="line"><span class="comment">#注意：如果配置了mybatis.configuration就不能再引入MyBatis的核心配置文件，因为两者都是同一种东西，都引入会报错   </span></span><br><span class="line"><span class="comment"># 可以不写全局；配置文件，所有全局配置文件的配置都放在configuration配置项中即可</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p><strong>SpringBoot整合MyBatis步骤：</strong></p>
</blockquote>
<ul>
<li>导入mybatis官方starter</li>
<li>编写mapper接口，标注@Mapper注解。就是写一个接口，在接口上使用@Mapper注解</li>
<li>编写sql映射文件并绑定mapper接口</li>
<li>在application.yaml中指定Mapper配置文件的位置，以及指定全局配置文件的信息 （建议；<strong>配置在mybatis.configuration，mybatis.configuration中配置的信息就相当于在MyBatis的全局配置文件中配置的信息</strong>）</li>
</ul>
<h5 id="1-3-2、注解模式"><a href="#1-3-2、注解模式" class="headerlink" title="1.3.2、注解模式"></a>1.3.2、注解模式</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Mapper</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">CityMapper</span> &#123;</span><br><span class="line"></span><br><span class="line">  <span class="meta">@Insert(&quot;INSERT INTO city (name, state, country) VALUES(#&#123;name&#125;, #&#123;state&#125;, #&#123;country&#125;)&quot;)</span></span><br><span class="line">  <span class="comment">//开启主键自增长，且主键回填，设置主键为 id</span></span><br><span class="line">  <span class="meta">@Options(useGeneratedKeys = true, keyProperty = &quot;id&quot;)</span></span><br><span class="line">  <span class="keyword">void</span> <span class="title function_">insert</span><span class="params">(City city)</span>;</span><br><span class="line"></span><br><span class="line">  <span class="meta">@Select(&quot;SELECT id, name, state, country FROM city WHERE id = #&#123;id&#125;&quot;)</span></span><br><span class="line">  City <span class="title function_">findById</span><span class="params">(<span class="type">long</span> id)</span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h5 id="1-3-3、混合模式"><a href="#1-3-3、混合模式" class="headerlink" title="1.3.3、混合模式"></a>1.3.3、混合模式</h5><p>注解版 + 配置版 = 混合版</p>
<h5 id="1-3-4、总结"><a href="#1-3-4、总结" class="headerlink" title="1.3.4、总结"></a>1.3.4、总结</h5><ul>
<li>引入mybatis-starter</li>
<li><strong>配置application.yaml中，指定mapper-location位置即可，不指定mapper-location就使用spring.configuration来替代mybatis的配置文件</strong></li>
<li>编写Mapper接口并标注@Mapper注解，也可以使用<code>@MapperScan(&quot;Mapper接口位置&quot;)</code>注解来扫描mapper接口的位置，接口就不需要<code>@Mapper</code>注解了</li>
<li>简单方法直接注解方式，<code>@Select，@Update ......</code></li>
<li>复杂方法编写mapper.xml进行绑定映射，简单SQL可以用注解，复杂SQL还是写配置文件</li>
<li>使用<code>使用@MapperScan(&quot;Map接口位置&quot;)</code> 简化开发后，其他的接口就可以不用标注@Mapper注解，<strong>但是最好还是给接口标上@Mapper注解</strong></li>
</ul>
<h4 id="1-4、整合MyBatisPlus"><a href="#1-4、整合MyBatisPlus" class="headerlink" title="1.4、整合MyBatisPlus"></a>1.4、整合MyBatisPlus</h4><h5 id="1-4-1、整合MyBatisPlus"><a href="#1-4-1、整合MyBatisPlus" class="headerlink" title="1.4.1、整合MyBatisPlus"></a>1.4.1、整合MyBatisPlus</h5><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.baomidou<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-plus-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>版本号<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="1-4-2、MP的自动配置"><a href="#1-4-2、MP的自动配置" class="headerlink" title="1.4.2、MP的自动配置"></a>1.4.2、MP的自动配置</h5><p>自动配置</p>
<ul>
<li>MybatisPlusAutoConfiguration 配置类，MybatisPlusProperties 配置项绑定。<strong>mybatis-plus：xxx 就是对**</strong>mybatis-plus的定制**</li>
<li><strong>SqlSessionFactory 自动配置好。底层是容器中默认的数据源</strong></li>
<li><strong>mapperLocations 自动配置好的。有默认值。**</strong>classpath*:/mapper/*<em>/\</em>.xml；任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件。  建议以后sql映射文件，放在 mapper下**</li>
<li><strong>容器中也自动配置好了</strong> <strong>SqlSessionTemplate</strong></li>
<li><strong>@Mapper 标注的接口也会被自动扫描；建议直接</strong> @MapperScan(<strong>“com.atguigu.admin.mapper”</strong>) 批量扫描就行</li>
</ul>
<h5 id="1-4-3、优点："><a href="#1-4-3、优点：" class="headerlink" title="1.4.3、优点："></a>1.4.3、<strong>优点：</strong></h5><ul>
<li>只需要我们的Mapper继承 <strong>BaseMapper</strong> 就可以拥有crud能力</li>
</ul>
<h4 id="1-4-4、简单CRUD"><a href="#1-4-4、简单CRUD" class="headerlink" title="1.4.4、简单CRUD"></a>1.4.4、简单CRUD</h4><p><strong>Service的实现类可以实现一个超级Service类，ServiceImpl<M extends BaseMapper< T >, T&gt;，可以不需要调用xxxMapper接口，就可以实现一些简单的CRUD</strong></p>
<p><strong>xxxMapper接口可以实现一个BaseMapper&lt; T &gt;接口，里面封装了一些简单的CRUD</strong></p>
<ul>
<li><p>使用</p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Service的实现类实现ServiceImpl实现类，里面封装了一些简单的CRUD</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">EmployeeServiceImpl</span> <span class="keyword">extends</span> <span class="title class_">ServiceImpl</span>&lt;EmployeeMapper, Employee&gt; <span class="keyword">implements</span> <span class="title class_">EmployeeService</span> &#123;   &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//XxxMapper接口继承BaseMapper&lt;T&gt; 可以进行一些简单的CRUD</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">EmployeeMapper</span> <span class="keyword">extends</span> <span class="title class_">BaseMapper</span>&lt;Employee&gt; &#123;   &#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="1-5、整合PageHelper插件"><a href="#1-5、整合PageHelper插件" class="headerlink" title="1.5、整合PageHelper插件"></a>1.5、整合PageHelper插件</h4><p><strong>GitHub地址：</strong></p>
<ul>
<li><a target="_blank" rel="noopener" href="https://hub.fastgit.org/pagehelper/pagehelper-spring-boot">https://hub.fastgit.org/pagehelper/pagehelper-spring-boot</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/pagehelper/pagehelper-spring-boot">https://github.com/pagehelper/pagehelper-spring-boot</a></li>
</ul>
<h5 id="1-5-1、引入Starter"><a href="#1-5-1、引入Starter" class="headerlink" title="1.5.1、引入Starter"></a>1.5.1、引入Starter</h5><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.github.pagehelper<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>pagehelper-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.3.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="1-5-2、简单使用："><a href="#1-5-2、简单使用：" class="headerlink" title="1.5.2、简单使用："></a>1.5.2、简单使用：</h5><ul>
<li><p>使用：（这里列举了两种使用方式）</p>
<ul>
<li><strong>PageHelper.offsetPage(参数1,参数2）</strong>==<strong>（参数一：从第几条数据开始查询，参数二：每页查询多少条数据）</strong>==</li>
<li><strong>PageHelper.startPage(参数一, 参数二);</strong>==<strong>（参数一：从第几页开始查询。参数二：每页显示多少条数据）</strong>==</li>
</ul>
</li>
</ul>
<pre><code>&gt; **这里只介绍了两种方法的使用，其他方法的使用可以去PageHelper官网查询使用**
</code></pre><h2 id="四、单元测试"><a href="#四、单元测试" class="headerlink" title="四、单元测试"></a>四、单元测试</h2><p>引入SpringBoot-Test的Starter</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="1、Junit5变化"><a href="#1、Junit5变化" class="headerlink" title="1、Junit5变化"></a>1、Junit5变化</h3><blockquote>
<p><strong>JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage</strong></p>
</blockquote>
<p><strong>JUnit Platform</strong>: Junit Platform是在JVM上启动测试框架的基础，不仅支持Junit自制的测试引擎，其他测试引擎也都可以接入。</p>
<p><strong>JUnit Jupiter</strong>: JUnit Jupiter提供了JUnit5的新的编程模型，是JUnit5新特性的核心。内部 包含了一个<strong>测试引擎</strong>，用于在Junit Platform上运行。</p>
<p><strong>JUnit Vintage</strong>: 由于JUint已经发展多年，为了照顾老的项目，JUnit Vintage提供了兼容JUnit4.x,Junit3.x的测试引擎。</p>
<p>注意：</p>
<p><strong>SpringBoot 2.4 以上版本移除了默认对 Vintage 的依赖。如果需要兼容junit4需要自行引入（不能使用junit4的功能 @Test）</strong></p>
<p><strong>JUnit 5’s Vintage Engine Removed from</strong> <strong><code>spring-boot-starter-test,如果需要继续兼容junit4需要自行引入vintage</code></strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.junit.vintage<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>junit-vintage-engine<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.hamcrest<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>hamcrest-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>以前：</p>
<p>@SpringBootTest + @RunWith(SpringTest.class)</p>
<p>SpringBoot整合Junit以后。</p>
<ul>
<li>编写测试方法：@Test标注（注意需要使用junit5版本的注解）</li>
<li><strong>Junit类具有Spring的功能，@Autowired、比如 @Transactional 标注测试方法，测试完成后自动回滚</strong></li>
</ul>
<h3 id="2、JUnit5常用注解"><a href="#2、JUnit5常用注解" class="headerlink" title="2、JUnit5常用注解"></a>2、JUnit5常用注解</h3><p><strong>Junit5官网：<a target="_blank" rel="noopener" href="https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations">https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations</a></strong></p>
<p>JUnit5的注解与JUnit4的注解有所变化</p>
<ul>
<li><p><strong>@Test :</strong>表示方法是测试方法。但是与JUnit4的@Test不同，他的职责非常单一不能声明任何属性，拓展的测试将会由Jupiter提供额外测试</p>
</li>
<li><p><strong>@ParameterizedTest :</strong>表示方法是参数化测试，下方会有详细介绍</p>
</li>
<li><p><strong>@RepeatedTest :</strong>表示方法可重复执行，下方会有详细介绍</p>
</li>
<li><p><strong>@DisplayName :</strong>为测试类或者测试方法设置展示名称</p>
</li>
<li><p><strong>@BeforeEach :</strong>表示在每个单元测试之前执行</p>
</li>
<li><p><strong>@AfterEach :</strong>表示在每个单元测试之后执行</p>
</li>
<li><p><strong>@BeforeAll :</strong>表示在所有单元测试之前执行</p>
</li>
<li><p><strong>@AfterAll :</strong>表示在所有单元测试之后执行</p>
</li>
<li><p><strong>@Tag :</strong>表示单元测试类别，类似于JUnit4中的@Categories</p>
</li>
<li><p><strong>@Disabled :</strong>表示测试类或测试方法不执行，类似于JUnit4中的@Ignore</p>
</li>
<li><p><strong>@Timeout :</strong>表示测试方法运行如果超过了指定时间将会返回错误</p>
</li>
<li><p><strong>@ExtendWith :</strong>为测试类或测试方法提供扩展类引用</p>
</li>
<li><p><strong>@RepeatedTest(5)</strong>：传入一个数字，标注在测试方法上，表示这个方法执行几次</p>
</li>
<li><p><strong>@Transactional：标注在ceshilei 或测试方法上，那么标注上该注解之后的增删改操作完成之后会数据回滚</strong></p>
</li>
</ul>
<h3 id="3、断言（assertions）"><a href="#3、断言（assertions）" class="headerlink" title="3、断言（assertions）"></a>3、断言（assertions）</h3><p>断言（assertions）是测试方法中的核心部分，用来对测试需要满足的条件进行验证。<strong>这些断言方法都是 org.junit.jupiter.api.Assertions 的静态方法</strong>。JUnit 5 内置的断言可以分成如下几个类别：</p>
<p><strong>检查业务逻辑返回的数据是否合理。</strong></p>
<p><strong>所有的测试运行结束以后，会有一个详细的测试报告；</strong></p>
<h4 id="3-1、简单断言"><a href="#3-1、简单断言" class="headerlink" title="3.1、简单断言"></a>3.1、简单断言</h4><div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">方法</th>
<th style="text-align:center">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">assertEquals</td>
<td style="text-align:center">判断两个对象或两个原始类型是否相等</td>
</tr>
<tr>
<td style="text-align:center">assertNotEquals</td>
<td style="text-align:center">判断两个对象或两个原始类型是否不相等</td>
</tr>
<tr>
<td style="text-align:center">assertSame</td>
<td style="text-align:center">判断两个对象引用是否指向同一个对象</td>
</tr>
<tr>
<td style="text-align:center">assertNotSame</td>
<td style="text-align:center">判断两个对象引用是否指向不同的对象</td>
</tr>
<tr>
<td style="text-align:center">assertTrue</td>
<td style="text-align:center">判断给定的布尔值是否为 true</td>
</tr>
<tr>
<td style="text-align:center">assertFalse</td>
<td style="text-align:center">判断给定的布尔值是否为 false</td>
</tr>
<tr>
<td style="text-align:center">assertNull</td>
<td style="text-align:center">判断给定的对象引用是否为 null</td>
</tr>
<tr>
<td style="text-align:center">assertNotNull</td>
<td style="text-align:center">判断给定的对象引用是否不为 null</td>
</tr>
</tbody>
</table>
</div>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;simple assertion&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">simple</span><span class="params">()</span> &#123;</span><br><span class="line">     assertEquals(<span class="number">3</span>, <span class="number">1</span> + <span class="number">2</span>, <span class="string">&quot;simple math&quot;</span>);</span><br><span class="line">     assertNotEquals(<span class="number">3</span>, <span class="number">1</span> + <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">     assertNotSame(<span class="keyword">new</span> <span class="title class_">Object</span>(), <span class="keyword">new</span> <span class="title class_">Object</span>());</span><br><span class="line">     <span class="type">Object</span> <span class="variable">obj</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line">     assertSame(obj, obj);</span><br><span class="line"></span><br><span class="line">     assertFalse(<span class="number">1</span> &gt; <span class="number">2</span>);</span><br><span class="line">     assertTrue(<span class="number">1</span> &lt; <span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">     assertNull(<span class="literal">null</span>);</span><br><span class="line">     assertNotNull(<span class="keyword">new</span> <span class="title class_">Object</span>());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-2、数组断言"><a href="#3-2、数组断言" class="headerlink" title="3.2、数组断言"></a>3.2、数组断言</h4><p>通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;array assertion&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">array</span><span class="params">()</span> &#123;</span><br><span class="line">    assertArrayEquals(<span class="keyword">new</span> <span class="title class_">int</span>[]&#123;<span class="number">1</span>, <span class="number">2</span>&#125;, <span class="keyword">new</span> <span class="title class_">int</span>[] &#123;<span class="number">1</span>, <span class="number">2</span>&#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-3、组合断言"><a href="#3-3、组合断言" class="headerlink" title="3.3、组合断言"></a>3.3、组合断言</h4><p>assertAll 方法接受多个 org.junit.jupiter.api.Executable 函数式接口的实例作为要验证的断言，可以通过 lambda 表达式很容易的提供这些断言</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;assert all&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">all</span><span class="params">()</span> &#123;</span><br><span class="line">    assertAll(<span class="string">&quot;Math&quot;</span>,</span><br><span class="line">              () -&gt; assertEquals(<span class="number">2</span>, <span class="number">1</span> + <span class="number">1</span>),</span><br><span class="line">              () -&gt; assertTrue(<span class="number">1</span> &gt; <span class="number">0</span>)</span><br><span class="line">             );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-4、异常断言"><a href="#3-4、异常断言" class="headerlink" title="3.4、异常断言"></a>3.4、异常断言</h4><p>在JUnit4时期，想要测试方法的异常情况时，需要用<strong>@Rule</strong>注解的ExpectedException变量还是比较麻烦的。而JUnit5提供了一种新的断言方式<strong>Assertions.assertThrows()</strong> ,配合函数式编程就可以进行使用。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;异常测试&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">exceptionTest</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ArithmeticException</span> <span class="variable">exception</span> <span class="operator">=</span> Assertions.assertThrows(</span><br><span class="line">        <span class="comment">//扔出断言异常</span></span><br><span class="line">        ArithmeticException.class, () -&gt; System.out.println(<span class="number">1</span> % <span class="number">0</span>));</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-5、超时断言"><a href="#3-5、超时断言" class="headerlink" title="3.5、超时断言"></a>3.5、超时断言</h4><p>Junit5还提供了<strong>Assertions.assertTimeout()</strong> 为测试方法设置了超时时间</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;超时测试&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">timeoutTest</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">//如果测试方法时间超过1s将会异常</span></span><br><span class="line">    Assertions.assertTimeout(Duration.ofMillis(<span class="number">1000</span>), () -&gt; Thread.sleep(<span class="number">500</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-6、快速失败"><a href="#3-6、快速失败" class="headerlink" title="3.6、快速失败"></a>3.6、快速失败</h4><p>通过 fail 方法直接使得测试失败    </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;fail&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">shouldFail</span><span class="params">()</span> &#123;</span><br><span class="line">    fail(<span class="string">&quot;This should fail&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="4、前置条件"><a href="#4、前置条件" class="headerlink" title="4、前置条件"></a>4、前置条件</h3><p>JUnit 5 中的前置条件（<strong>assumptions【假设】</strong>）类似于断言，不同之处在于<strong>不满足的断言会使得测试方法失败</strong>，而不满足的<strong>前置条件只会使得测试方法的执行终止</strong>。前置条件可以看成是测试方法执行的前提，当该前提不满足时，就没有继续执行的必要。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@DisplayName(&quot;前置条件&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AssumptionsTest</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">environment</span> <span class="operator">=</span> <span class="string">&quot;DEV&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="meta">@DisplayName(&quot;simple&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">simpleAssume</span><span class="params">()</span> &#123;</span><br><span class="line">        assumeTrue(Objects.equals(<span class="built_in">this</span>.environment, <span class="string">&quot;DEV&quot;</span>));</span><br><span class="line">        assumeFalse(() -&gt; Objects.equals(<span class="built_in">this</span>.environment, <span class="string">&quot;PROD&quot;</span>));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="meta">@DisplayName(&quot;assume then do&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">assumeThenDo</span><span class="params">()</span> &#123;</span><br><span class="line">        assumingThat(</span><br><span class="line">            Objects.equals(<span class="built_in">this</span>.environment, <span class="string">&quot;DEV&quot;</span>),</span><br><span class="line">            () -&gt; System.out.println(<span class="string">&quot;In DEV&quot;</span>)</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>assumeTrue 和 assumFalse 确保给定的条件为 true 或 false，不满足条件会使得测试执行终止。assumingThat 的参数是表示条件的布尔值和对应的 Executable 接口的实现对象。只有条件满足时，Executable 对象才会被执行；当条件不满足时，测试执行并不会终止。</p>
<h3 id="5、嵌套测试"><a href="#5、嵌套测试" class="headerlink" title="5、嵌套测试"></a>5、嵌套测试</h3><p>JUnit 5 可以通过 Java 中的内部类和@Nested 注解实现嵌套测试，从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用@BeforeEach 和@AfterEach 注解，而且嵌套的层次没有限制。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@DisplayName(&quot;A stack&quot;)</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">TestingAStackDemo</span> &#123;</span><br><span class="line"></span><br><span class="line">    Stack&lt;Object&gt; stack;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="meta">@DisplayName(&quot;is instantiated with new Stack()&quot;)</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">isInstantiatedWithNew</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">Stack</span>&lt;&gt;();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Nested</span></span><br><span class="line">    <span class="meta">@DisplayName(&quot;when new&quot;)</span></span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">WhenNew</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@BeforeEach</span></span><br><span class="line">        <span class="keyword">void</span> <span class="title function_">createNewStack</span><span class="params">()</span> &#123;</span><br><span class="line">            stack = <span class="keyword">new</span> <span class="title class_">Stack</span>&lt;&gt;();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Test</span></span><br><span class="line">        <span class="meta">@DisplayName(&quot;is empty&quot;)</span></span><br><span class="line">        <span class="keyword">void</span> <span class="title function_">isEmpty</span><span class="params">()</span> &#123;</span><br><span class="line">            assertTrue(stack.isEmpty());</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Test</span></span><br><span class="line">        <span class="meta">@DisplayName(&quot;throws EmptyStackException when popped&quot;)</span></span><br><span class="line">        <span class="keyword">void</span> <span class="title function_">throwsExceptionWhenPopped</span><span class="params">()</span> &#123;</span><br><span class="line">            assertThrows(EmptyStackException.class, stack::pop);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Test</span></span><br><span class="line">        <span class="meta">@DisplayName(&quot;throws EmptyStackException when peeked&quot;)</span></span><br><span class="line">        <span class="keyword">void</span> <span class="title function_">throwsExceptionWhenPeeked</span><span class="params">()</span> &#123;</span><br><span class="line">            assertThrows(EmptyStackException.class, stack::peek);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Nested</span></span><br><span class="line">        <span class="meta">@DisplayName(&quot;after pushing an element&quot;)</span></span><br><span class="line">        <span class="keyword">class</span> <span class="title class_">AfterPushing</span> &#123;</span><br><span class="line"></span><br><span class="line">            <span class="type">String</span> <span class="variable">anElement</span> <span class="operator">=</span> <span class="string">&quot;an element&quot;</span>;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@BeforeEach</span></span><br><span class="line">            <span class="keyword">void</span> <span class="title function_">pushAnElement</span><span class="params">()</span> &#123;</span><br><span class="line">                stack.push(anElement);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Test</span></span><br><span class="line">            <span class="meta">@DisplayName(&quot;it is no longer empty&quot;)</span></span><br><span class="line">            <span class="keyword">void</span> <span class="title function_">isNotEmpty</span><span class="params">()</span> &#123;</span><br><span class="line">                assertFalse(stack.isEmpty());</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Test</span></span><br><span class="line">            <span class="meta">@DisplayName(&quot;returns the element when popped and is empty&quot;)</span></span><br><span class="line">            <span class="keyword">void</span> <span class="title function_">returnElementWhenPopped</span><span class="params">()</span> &#123;</span><br><span class="line">                assertEquals(anElement, stack.pop());</span><br><span class="line">                assertTrue(stack.isEmpty());</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Test</span></span><br><span class="line">            <span class="meta">@DisplayName(&quot;returns the element when peeked but remains not empty&quot;)</span></span><br><span class="line">            <span class="keyword">void</span> <span class="title function_">returnElementWhenPeeked</span><span class="params">()</span> &#123;</span><br><span class="line">                assertEquals(anElement, stack.peek());</span><br><span class="line">                assertFalse(stack.isEmpty());</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="6、参数化测试"><a href="#6、参数化测试" class="headerlink" title="6、参数化测试"></a>6、参数化测试</h3><p>参数化测试是JUnit5很重要的一个新特性，它使得用不同的参数多次运行测试成为了可能，也为我们的单元测试带来许多便利。</p>
<p>利用<strong>@ValueSource</strong>等注解，指定入参，我们将可以使用不同的参数进行多次单元测试，而不需要每新增一个参数就新增一个单元测试，省去了很多冗余代码。</p>
<p><strong>@ValueSource</strong>: 为参数化测试指定入参来源，支持八大基础类以及String类型,Class类型</p>
<p><strong>@NullSource</strong>: 表示为参数化测试提供一个null的入参</p>
<p><strong>@EnumSource</strong>: 表示为参数化测试提供一个枚举入参</p>
<p><strong>@CsvFileSource</strong>：表示读取指定CSV文件内容作为参数化测试入参</p>
<p><strong>@MethodSource</strong>：表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)</p>
<blockquote>
<p>当然如果参数化测试仅仅只能做到指定普通的入参还达不到让我觉得惊艳的地步。让我真正感到他的强大之处的地方在于他可以支持外部的各类入参。如:CSV,YML,JSON 文件甚至方法的返回值也可以作为入参。只需要去实现<strong>ArgumentsProvider</strong>接口，任何外部文件都可以作为它的入参。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ParameterizedTest</span></span><br><span class="line"><span class="meta">@ValueSource(strings = &#123;&quot;one&quot;, &quot;two&quot;, &quot;three&quot;&#125;)</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;参数化测试1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">parameterizedTest1</span><span class="params">(String string)</span> &#123;</span><br><span class="line">    System.out.println(string);</span><br><span class="line">    Assertions.assertTrue(StringUtils.isNotBlank(string));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@ParameterizedTest</span></span><br><span class="line"><span class="meta">@MethodSource(&quot;method&quot;)</span>    <span class="comment">//指定方法名</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;方法来源参数&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testWithExplicitLocalMethodSource</span><span class="params">(String name)</span> &#123;</span><br><span class="line">    System.out.println(name);</span><br><span class="line">    Assertions.assertNotNull(name);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">static</span> Stream&lt;String&gt; <span class="title function_">method</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> Stream.of(<span class="string">&quot;apple&quot;</span>, <span class="string">&quot;banana&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="7、Junit4迁移到Junit5指南"><a href="#7、Junit4迁移到Junit5指南" class="headerlink" title="7、Junit4迁移到Junit5指南"></a>7、Junit4迁移到Junit5指南</h3><p>在进行迁移的时候需要注意如下的变化：</p>
<ul>
<li>注解在 org.junit.jupiter.api 包中，断言在 org.junit.jupiter.api.Assertions 类中，前置条件在 org.junit.jupiter.api.Assumptions 类中。</li>
<li>把@Before 和@After 替换成@BeforeEach 和@AfterEach。</li>
<li>把@BeforeClass 和@AfterClass 替换成@BeforeAll 和@AfterAll。</li>
<li>把@Ignore 替换成@Disabled。</li>
<li>把@Category 替换成@Tag。</li>
<li>把@RunWith、@Rule 和@ClassRule 替换成@ExtendWith。</li>
</ul>
<h2 id="五、指标监控"><a href="#五、指标监控" class="headerlink" title="五、指标监控"></a>五、指标监控</h2><h3 id="1、SpringBoot-Actuator"><a href="#1、SpringBoot-Actuator" class="headerlink" title="1、SpringBoot Actuator"></a>1、SpringBoot Actuator</h3><h4 id="1-1、简介"><a href="#1-1、简介" class="headerlink" title="1.1、简介"></a>1.1、简介</h4><p>未来每一个微服务在云上部署以后，我们都需要对其进行监控、追踪、审计、控制等。SpringBoot就抽取了Actuator场景，使得我们每个微服务快速引用即可获得生产级别的应用监控、审计等功能。</p>
<ul>
<li><p>引入SpringBoot Actuator</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-actuator<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="1-2、1-x与2-x的不同"><a href="#1-2、1-x与2-x的不同" class="headerlink" title="1.2、1.x与2.x的不同"></a>1.2、1.x与2.x的不同</h4><p><img src= "" data-lazy-src="https://www.naste.top:9000/webp/SpringBootActuator-1.x%E4%B8%8E2.x%E7%9A%84%E5%8C%BA%E5%88%AB.webp" alt="SpringBootActuator-1.x与2.x的区别"></p>
<h4 id="1-3、如何使用"><a href="#1-3、如何使用" class="headerlink" title="1.3、如何使用"></a>1.3、如何使用</h4><ul>
<li><p>引入场景</p>
</li>
<li><p>访问 <a target="_blank" rel="noopener" href="http://localhost:8080/actuator/**">http://localhost:8080/actuator/**</a></p>
</li>
<li><p>在配置文件中配置将所有指标监控暴露所有监控信息为HTTP，设置可以在浏览器中访问</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">management:</span></span><br><span class="line">  <span class="attr">endpoints:</span></span><br><span class="line">    <span class="attr">enabled-by-default:</span> <span class="literal">true</span> <span class="comment">#暴露所有端点信息</span></span><br><span class="line">    <span class="attr">web:</span></span><br><span class="line">      <span class="attr">exposure:</span></span><br><span class="line">        <span class="attr">include:</span> <span class="string">&#x27;*&#x27;</span>  <span class="comment">#以web方式暴露</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>测试：</p>
<ul>
<li><a target="_blank" rel="noopener" href="http://localhost:8080/actuator/beans">http://localhost:8080/actuator/beans</a></li>
<li><a target="_blank" rel="noopener" href="http://localhost:8080/actuator/configprops">http://localhost:8080/actuator/configprops</a></li>
<li><a target="_blank" rel="noopener" href="http://localhost:8080/actuator/metrics">http://localhost:8080/actuator/metrics</a></li>
<li><a target="_blank" rel="noopener" href="http://localhost:8080/actuator/metrics/jvm.gc.pause">http://localhost:8080/actuator/metrics/jvm.gc.pause</a></li>
<li><a target="_blank" rel="noopener" href="http://localhost:8080/actuator/metrics">http://localhost:8080/actuator/</a>endpointName/detailPath</li>
<li>。。。。。。。</li>
</ul>
</li>
</ul>
<h4 id="1-4、可视化"><a href="#1-4、可视化" class="headerlink" title="1.4、可视化"></a>1.4、可视化</h4><p><strong>GitHub地址：<a target="_blank" rel="noopener" href="https://github.com/codecentric/spring-boot-admin">https://github.com/codecentric/spring-boot-admin</a></strong></p>
<ul>
<li><p>第一步：专门写一个服务器用来监控其他客户端服务器信息：</p>
<ul>
<li><p>引入Starter</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--SpringBoot指标监控可视化--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>de.codecentric<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-admin-starter-server<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.3.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>修改端口号避免重复：</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">server.port=8888</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>第二步：将客户端给管理员端监控</p>
<ul>
<li><p>引入starter</p>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--客户端的client-stater--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>de.codecentric<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-admin-starter-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.3.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>修改一些配置信息</p>
  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">management:</span></span><br><span class="line">  <span class="attr">endpoints:</span></span><br><span class="line">    <span class="attr">enabled-by-default:</span> <span class="literal">true</span> <span class="comment">#暴露所有端点信息</span></span><br><span class="line">    <span class="attr">web:</span></span><br><span class="line">      <span class="attr">exposure:</span></span><br><span class="line">        <span class="attr">include:</span> <span class="string">&#x27;*&#x27;</span>  <span class="comment">#以web方式暴露</span></span><br><span class="line">        </span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">boot:</span></span><br><span class="line">    <span class="attr">admin:</span></span><br><span class="line">      <span class="attr">client:</span></span><br><span class="line">        <span class="attr">url:</span> <span class="string">http://localhost:8888</span> <span class="comment">#admin端的地址</span></span><br><span class="line">        <span class="attr">instance:</span></span><br><span class="line">          <span class="attr">prefer-ip:</span> <span class="literal">true</span> <span class="comment">#使用IP注册</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">springboot_04_data</span> <span class="comment">#一般将名字改为项目名称</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>其他具体使用查看官方文档</strong></p>
</blockquote>
<h3 id="2、Actuator-Endpoint"><a href="#2、Actuator-Endpoint" class="headerlink" title="2、Actuator Endpoint"></a>2、Actuator Endpoint</h3><p><strong>其他指标监控笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/sgpvgn#KBTP3">https://www.yuque.com/atguigu/springboot/sgpvgn#KBTP3</a></strong></p>
<h4 id="2-1、最常使用的端点"><a href="#2-1、最常使用的端点" class="headerlink" title="2.1、最常使用的端点"></a>2.1、最常使用的端点</h4><div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">ID</th>
<th style="text-align:center">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>auditevents</code></td>
<td style="text-align:center">暴露当前应用程序的审核事件信息。需要一个<code>AuditEventRepository组件</code>。</td>
</tr>
<tr>
<td style="text-align:center"><code>beans</code></td>
<td style="text-align:center">显示应用程序中所有Spring Bean的完整列表。</td>
</tr>
<tr>
<td style="text-align:center"><code>caches</code></td>
<td style="text-align:center">暴露可用的缓存。</td>
</tr>
<tr>
<td style="text-align:center"><code>conditions</code></td>
<td style="text-align:center">显示自动配置的所有条件信息，包括匹配或不匹配的原因。</td>
</tr>
<tr>
<td style="text-align:center"><code>configprops</code></td>
<td style="text-align:center">显示所有<code>@ConfigurationProperties</code>。</td>
</tr>
<tr>
<td style="text-align:center"><code>env</code></td>
<td style="text-align:center">暴露Spring的属性<code>ConfigurableEnvironment</code></td>
</tr>
<tr>
<td style="text-align:center"><code>flyway</code></td>
<td style="text-align:center">显示已应用的所有Flyway数据库迁移。 需要一个或多个<code>Flyway</code>组件。</td>
</tr>
<tr>
<td style="text-align:center"><code>health</code></td>
<td style="text-align:center">显示应用程序运行状况信息。</td>
</tr>
<tr>
<td style="text-align:center"><code>httptrace</code></td>
<td style="text-align:center">显示HTTP跟踪信息（默认情况下，最近100个HTTP请求-响应）。需要一个<code>HttpTraceRepository</code>组件。</td>
</tr>
<tr>
<td style="text-align:center"><code>info</code></td>
<td style="text-align:center">显示应用程序信息。</td>
</tr>
<tr>
<td style="text-align:center"><code>integrationgraph</code></td>
<td style="text-align:center">显示Spring <code>integrationgraph</code> 。需要依赖<code>spring-integration-core</code>。</td>
</tr>
<tr>
<td style="text-align:center"><code>loggers</code></td>
<td style="text-align:center">显示和修改应用程序中日志的配置。</td>
</tr>
<tr>
<td style="text-align:center"><code>liquibase</code></td>
<td style="text-align:center">显示已应用的所有Liquibase数据库迁移。需要一个或多个<code>Liquibase</code>组件。</td>
</tr>
<tr>
<td style="text-align:center"><code>metrics</code></td>
<td style="text-align:center">显示当前应用程序的“指标”信息。</td>
</tr>
<tr>
<td style="text-align:center"><code>mappings</code></td>
<td style="text-align:center">显示所有<code>@RequestMapping</code>路径列表。</td>
</tr>
<tr>
<td style="text-align:center"><code>scheduledtasks</code></td>
<td style="text-align:center">显示应用程序中的计划任务。</td>
</tr>
<tr>
<td style="text-align:center"><code>sessions</code></td>
<td style="text-align:center">允许从Spring Session支持的会话存储中检索和删除用户会话。需要使用Spring Session的基于Servlet的Web应用程序。</td>
</tr>
<tr>
<td style="text-align:center"><code>shutdown</code></td>
<td style="text-align:center">使应用程序正常关闭。默认禁用。</td>
</tr>
<tr>
<td style="text-align:center"><code>startup</code></td>
<td style="text-align:center">显示由<code>ApplicationStartup</code>收集的启动步骤数据。需要使用</td>
</tr>
<tr>
<td style="text-align:center"><code>startup</code></td>
<td style="text-align:center">显示由<code>ApplicationStartup</code>收集的启动步骤数据。需要使用<code>SpringApplication</code>进行配置<code>BufferingApplicationStartup</code>。</td>
</tr>
<tr>
<td style="text-align:center"><code>threaddump</code></td>
<td style="text-align:center">执行线程转储。</td>
</tr>
</tbody>
</table>
</div>
<blockquote>
<p><strong>还想了解其他信息可以去</strong></p>
<p><strong>官网：<a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready">https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready</a> </strong></p>
<p><strong>笔记：<a target="_blank" rel="noopener" href="https://www.yuque.com/atguigu/springboot/sgpvgn">https://www.yuque.com/atguigu/springboot/sgpvgn</a></strong></p>
</blockquote>
<h2 id="六、原理解析"><a href="#六、原理解析" class="headerlink" title="六、原理解析"></a>六、原理解析</h2><h1 id="跨域问题"><a href="#跨域问题" class="headerlink" title="跨域问题"></a>跨域问题</h1><h2 id="一、在SpringBoot中解决跨域问题"><a href="#一、在SpringBoot中解决跨域问题" class="headerlink" title="一、在SpringBoot中解决跨域问题"></a>一、在SpringBoot中解决跨域问题</h2><blockquote>
<p><strong>写一个配置类实现WebMvcConfigurer</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.southwind.configuration;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.config.annotation.CorsRegistry;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.config.annotation.WebMvcConfigurer;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CrossConfiguration</span> <span class="keyword">implements</span> <span class="title class_">WebMvcConfigurer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addCorsMappings</span><span class="params">(CorsRegistry registry)</span> &#123;</span><br><span class="line">        registry.addMapping(<span class="string">&quot;/**&quot;</span>)</span><br><span class="line">                .allowedOriginPatterns(<span class="string">&quot;*&quot;</span>)</span><br><span class="line">                .allowedMethods(<span class="string">&quot;GET&quot;</span>, <span class="string">&quot;HEAD&quot;</span>, <span class="string">&quot;POST&quot;</span>, <span class="string">&quot;PUT&quot;</span>, <span class="string">&quot;DELETE&quot;</span>, <span class="string">&quot;OPTIONS&quot;</span>)</span><br><span class="line">                .allowCredentials(<span class="literal">true</span>)</span><br><span class="line">                .maxAge(<span class="number">3600</span>)</span><br><span class="line">                .allowedHeaders(<span class="string">&quot;*&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p><strong>在控制器上写一个<code>@CrossOrigin</code>用来解决跨域问题</strong></p>
</blockquote>
<h2 id="二、跨域的时候绑定Cookie出现的问题"><a href="#二、跨域的时候绑定Cookie出现的问题" class="headerlink" title="二、跨域的时候绑定Cookie出现的问题"></a>二、跨域的时候绑定Cookie出现的问题</h2><p><strong>由于前后端分离项目中，请求后端是默认不带Cookie的信息的，所以，每次请求后端的session的值是不一样的。后端对于是否重新创建Session是取决与Cookie中是否有 <code>JSESSIONID</code>，所以为了保证session不是每次请求都是重新创建的，下面分别有前端和后端的代码，两端代码都要写</strong></p>
<ul>
<li><p><strong>前端（在Vue的main.js文件中添加）：</strong></p>
  <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//直接在Vue的原型中引入，再设置Axios的基路径，到后面使用axios发送请求路径前面都会加上该路径</span></span><br><span class="line">axios.<span class="property">defaults</span>.<span class="property">baseURL</span> = <span class="string">&quot;http://localhost:8100&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//请求超时时间</span></span><br><span class="line">axios.<span class="property">defaults</span>.<span class="property">timeout</span> = <span class="number">10000</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//post请求头</span></span><br><span class="line">axios.<span class="property">defaults</span>.<span class="property">headers</span>.<span class="property">post</span>[<span class="string">&#x27;Content-Type&#x27;</span>] = <span class="string">&#x27;application/x-www-form-urlencoded;charset=utf-8&#x27;</span>;</span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//设置cross跨域 并设置访问权限 允许跨域携带cookie信息，</span></span><br><span class="line"><span class="comment">// 如果不携带cookie信息，那么跨域每次请求服务器都会重新创建一个session，因为session的JSESSIONID是保存在浏览器的cookie中的</span></span><br><span class="line">axios.<span class="property">defaults</span>.<span class="property">withCredentials</span>=<span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$http</span> = axios <span class="comment">//全局注册axios，使用方法为：this.$http.GET/POST/DELETE/PUT</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p><strong>后端（写一个解决跨域问题的配置类）：</strong></p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.config.annotation.CorsRegistry;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.config.annotation.WebMvcConfigurer;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 解决前后端分离引发的跨域问题</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CrossConfiguration</span> <span class="keyword">implements</span> <span class="title class_">WebMvcConfigurer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 注意：如果想要在前端请求的时候携带cookie信息，allowedOriginPatterns的值不能设置为 * ，</span></span><br><span class="line"><span class="comment">     * 需要将值设置为前端的工程路径，可以设置多个请求的路径，每个用 ’,‘隔开</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addCorsMappings</span><span class="params">(CorsRegistry registry)</span> &#123;</span><br><span class="line">        registry.addMapping(<span class="string">&quot;/**&quot;</span>)</span><br><span class="line">                .allowedOriginPatterns(</span><br><span class="line">                        <span class="string">&quot;http://localhost:8080&quot;</span>,</span><br><span class="line">                        <span class="string">&quot;http://localhost:8081&quot;</span>,</span><br><span class="line">                        <span class="string">&quot;http://localhost:8082&quot;</span>,</span><br><span class="line">                        <span class="string">&quot;http://localhost:8083&quot;</span>)</span><br><span class="line">                .allowedMethods(<span class="string">&quot;GET&quot;</span>, <span class="string">&quot;HEAD&quot;</span>, <span class="string">&quot;POST&quot;</span>, <span class="string">&quot;PUT&quot;</span>, <span class="string">&quot;DELETE&quot;</span>, <span class="string">&quot;OPTIONS&quot;</span>)</span><br><span class="line">                .allowCredentials(<span class="literal">true</span>)</span><br><span class="line">                .maxAge(<span class="number">3600</span>)</span><br><span class="line">                .allowedHeaders(<span class="string">&quot;*&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h1 id="SpringBoot整合Vue中的问题"><a href="#SpringBoot整合Vue中的问题" class="headerlink" title="SpringBoot整合Vue中的问题"></a>SpringBoot整合Vue中的问题</h1><h2 id="1、Cookie的问题"><a href="#1、Cookie的问题" class="headerlink" title="1、Cookie的问题"></a>1、Cookie的问题</h2><blockquote>
<p><strong>前后端分离开发Cookie的跨域问题，请求中有Cookie信息，但浏览器本地却没有Cookie信息</strong></p>
</blockquote>
<p><strong>解决方法：不再使用Servlet中原生的设置Cookie的方式设置Cookie，而是使用 <code>ResponseCookie</code>来设置Cookie</strong></p>
<ul>
<li><p><strong>设置Cookie（写成一个工具类，用的时候直接调用就行了）：</strong></p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 用于保存cookie的值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> name cookie的键</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> value cookie的值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 返回cookie的信息</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> ResponseCookie <span class="title function_">setCookie</span><span class="params">(String name, String value)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> ResponseCookie.from(name, value) <span class="comment">// key &amp; value</span></span><br><span class="line">            .httpOnly(<span class="literal">false</span>)     <span class="comment">//是否禁止js读取设置为true，允许js读取为false</span></span><br><span class="line">            .secure(<span class="literal">true</span>)      <span class="comment">//是否在http下也传输，设置true在http下也传输，设置为false只能在https下传输</span></span><br><span class="line">            .domain(<span class="string">&quot;localhost&quot;</span>)<span class="comment">// 设置域名</span></span><br><span class="line">            .path(<span class="string">&quot;/&quot;</span>)          <span class="comment">// path</span></span><br><span class="line">            .maxAge(Duration.ofHours(<span class="number">1</span>))    <span class="comment">// 1个小时候过期</span></span><br><span class="line">            .sameSite(<span class="string">&quot;Lax&quot;</span>)    <span class="comment">// 大多数情况也是不发送第三方 Cookie，但是导航到目标网址的 Get 请求除外</span></span><br><span class="line">            .build();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>将Cookie的信息通知浏览器保存：</strong></p>
  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//调用封装好的工具类来设置Cookie的值</span></span><br><span class="line"><span class="comment">// 设置Cookie Header</span></span><br><span class="line">response.setHeader(HttpHeaders.SET_COOKIE, String.valueOf(WebUtils.setCookie(<span class="string">&quot;myCookie&quot;</span>,<span class="string">&quot;myCookieValue&quot;</span>)));</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p><strong>具体原因：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/6707ad6a793f">https://www.jianshu.com/p/6707ad6a793f</a></strong></p>
<h2 id="2、数据库问题"><a href="#2、数据库问题" class="headerlink" title="2、数据库问题"></a>2、数据库问题</h2><blockquote>
<p><strong>mybatisplus数据库没有的字段实体类如何处理：【比如：JavaBean中的属性值为另外一个JavaBean的时候可以使用@TableField( exist = false )】</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 使用 <span class="doctag">@TableField</span>(exist = false) ，表示该字段在数据库中不存在 ，所以不会插入数据库中</span></span><br><span class="line"><span class="comment"> * 使用 transient 、 static 修饰属性也不会插入数据库中</span></span><br><span class="line"><span class="comment"> * 在属性或get方法上声明注解<span class="doctag">@TableField</span>(exist = false)</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>
<h2 id="3、日期格式化问题"><a href="#3、日期格式化问题" class="headerlink" title="3、日期格式化问题"></a>3、日期格式化问题</h2><blockquote>
<p><strong>后台解决</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在JavaBean日期类的字段上加上如下注解</span></span><br><span class="line"><span class="meta">@DateTimeFormat(pattern = &quot;yyyy-MM-dd&quot;)</span></span><br><span class="line"><span class="meta">@JsonFormat(pattern = &quot;yyyy-MM-dd&quot;, timezone = &quot;GMT+8&quot;)</span></span><br><span class="line"><span class="meta">@JSONField(format = &quot;yyyy-MM-dd&quot;)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<blockquote>
<p><strong>前端解决：使用momunt过滤器</strong></p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//进行全局定义过滤器</span></span><br><span class="line"><span class="comment">//npm install moment -S</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//第一步、在main.js中</span></span><br><span class="line"><span class="keyword">import</span> moment <span class="keyword">from</span> ‘moment/moment’</span><br><span class="line"></span><br><span class="line"><span class="comment">//定义全局时间过滤器</span></span><br><span class="line"><span class="comment">// 定义过滤器</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">filter</span>(<span class="string">&#x27;dateString&#x27;</span>, <span class="keyword">function</span> (<span class="params">value, format = <span class="string">&#x27;YYYY-MM-DD HH:mm:ss&#x27;</span></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">moment</span>(value).<span class="title function_">format</span>(format);</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">//在页面中使用</span></span><br><span class="line">&#123;&#123; book.<span class="property">addTime</span> | dateString &#125;&#125;</span><br></pre></td></tr></table></figure>
<h2 id="4、SpringBoot拦截器获取不到Session的值"><a href="#4、SpringBoot拦截器获取不到Session的值" class="headerlink" title="4、SpringBoot拦截器获取不到Session的值"></a>4、SpringBoot拦截器获取不到Session的值</h2><blockquote>
<p><strong>在拦截器开始前加上如下代码：</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (request.getMethod().equals(<span class="string">&quot;OPTIONS&quot;</span>)) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>为什么SpringBoot拦截器取不到Session值的原因：<a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_45059962/article/details/111104137">https://blog.csdn.net/weixin_45059962/article/details/111104137</a></strong></p>
<h1 id="Vue使用遇到的问题"><a href="#Vue使用遇到的问题" class="headerlink" title="Vue使用遇到的问题"></a>Vue使用遇到的问题</h1><h2 id="一、点击事件"><a href="#一、点击事件" class="headerlink" title="一、点击事件"></a>一、点击事件</h2><p><strong>在点击事件加上 【 .native 】表示使用原生的事件，而不是Vue提供的，例如 @click.native</strong></p>
<blockquote>
<p><strong>在Vue中使用@click点击事件没有用：下面连接具体原因</strong></p>
<p><strong><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_41646716/article/details/90069562">https://blog.csdn.net/weixin_41646716/article/details/90069562</a></strong></p>
</blockquote>
<h2 id="二、拦截事件"><a href="#二、拦截事件" class="headerlink" title="二、拦截事件"></a>二、拦截事件</h2><blockquote>
<p><strong>当被后台的拦截器拦截成功后返回的的结果为 ‘’ ，一个空的字符串</strong></p>
</blockquote>
<h2 id="三、使用Vue进行文件上传"><a href="#三、使用Vue进行文件上传" class="headerlink" title="三、使用Vue进行文件上传"></a>三、使用Vue进行文件上传</h2><blockquote>
<p><strong>使用ElementUI进行文件上传时遇到的问题</strong></p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- action属性必填。提交的方式默认为POST，默认是不携带Cookie信息的，需要将with-credentials设置为True，才会携带Cooie信息 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">el-form</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">el-form-item</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">el-upload</span> <span class="attr">class</span>=<span class="string">&quot;upload-demo&quot;</span> <span class="attr">drag</span> <span class="attr">accept</span>=<span class="string">&quot;image/jpg&quot;</span></span></span><br><span class="line"><span class="tag">                   <span class="attr">with-credentials</span></span></span><br><span class="line"><span class="tag">                   <span class="attr">name</span>=<span class="string">&quot;userImg&quot;</span> <span class="attr">:action</span>=<span class="string">&quot;requestURL+&#x27;user/admin/updateImg&#x27;&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;el-icon-upload&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;el-upload__text&quot;</span>&gt;</span>将文件拖到此处，或<span class="tag">&lt;<span class="name">em</span>&gt;</span>点击上传<span class="tag">&lt;/<span class="name">em</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;el-upload__tip&quot;</span> <span class="attr">slot</span>=<span class="string">&quot;tip&quot;</span>&gt;</span>只能上传jpg文件，且不超过10MB<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">el-upload</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">el-form-item</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">el-form</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h2 id="三、axios的使用"><a href="#三、axios的使用" class="headerlink" title="三、axios的使用"></a>三、axios的使用</h2><h2 id="1、在axios中，param和data属性的区别"><a href="#1、在axios中，param和data属性的区别" class="headerlink" title="1、在axios中，param和data属性的区别"></a>1、在axios中，param和data属性的区别</h2><ul>
<li><p>因为params是添加到url的请求字符串中的，用于get请求。 </p>
</li>
<li><p>而data是添加到请求体（body）中的， 用于post请求。</p>
</li>
<li>详细区别：<strong><a target="_blank" rel="noopener" href="https://www.cnblogs.com/cwzqianduan/p/8675356.html">https://www.cnblogs.com/cwzqianduan/p/8675356.html</a></strong></li>
</ul>
<h2 id="2、使用axios传参的问题"><a href="#2、使用axios传参的问题" class="headerlink" title="2、使用axios传参的问题"></a>2、使用axios传参的问题</h2><p><strong>问题：在使用axios的POST方法传参数的时候，前端传了值，后端接收不到值</strong></p>
<blockquote>
<p><strong>对于上述问题：可以先使用 <code>URLSearchParams</code>将参数保存，再传入给后端</strong></p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//使用axios的post方法传入参数，直接加在data属性中，前端可能传入了参数，但是后台却就收不到</span></span><br><span class="line"><span class="comment">//这时可以使用URLSearchParams来将值保存，用于传入后台</span></span><br><span class="line"><span class="keyword">let</span> param = <span class="keyword">new</span> <span class="title class_">URLSearchParams</span>();</span><br><span class="line">param.<span class="title function_">append</span>(<span class="string">&quot;address&quot;</span>, address);</span><br><span class="line">param.<span class="title function_">append</span>(<span class="string">&quot;carts&quot;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(<span class="variable language_">this</span>.<span class="property">multipleSelection</span>));</span><br><span class="line"></span><br><span class="line"><span class="variable language_">this</span>.$http(&#123;</span><br><span class="line">    <span class="attr">method</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">    <span class="attr">url</span>: <span class="string">&quot;/user/admin/order&quot;</span>,</span><br><span class="line">    <span class="attr">data</span>: param,</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
</article><div class="post-copyright"><div class="post-copyright__title"><span class="post-copyright-info"><h>SpringBoot</h></span></div><div class="post-copyright__type"><span class="post-copyright-info"><a href="https://www.naste.top:1024/posts/1864766114.html">https://www.naste.top:1024/posts/1864766114.html</a></span></div><div class="post-copyright-m"><div class="post-copyright-m-info"><div class="post-copyright-a"><h>作者</h><div class="post-copyright-cc-info"><h>XiaoFei🥝</h></div></div><div class="post-copyright-c"><h>发布于</h><div class="post-copyright-cc-info"><h>2022-06-15</h></div></div><div class="post-copyright-u"><h>更新于</h><div class="post-copyright-cc-info"><h>2024-04-26</h></div></div><div class="post-copyright-c"><h>许可协议</h><div class="post-copyright-cc-info"><a class="icon" rel="noopener" target="_blank" title="Creative Commons" href="https://creativecommons.org/"><i class="fab fa-creative-commons"></i></a><a rel="noopener" target="_blank" title="CC BY-NC-SA 4.0" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a></div></div></div></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Java/"><div class="tags-punctuation"><svg class="faa-tada icon" style="height:1.1em;width:1.1em;fill:currentColor;position:relative;top:2px;margin-right:3px" aria-hidden="true"><use xlink:href="#icon-sekuaibiaoqian"></use></svg></div>Java</a><a class="post-meta__tags" href="/tags/SpringBoot/"><div class="tags-punctuation"><svg class="faa-tada icon" style="height:1.1em;width:1.1em;fill:currentColor;position:relative;top:2px;margin-right:3px" aria-hidden="true"><use xlink:href="#icon-sekuaibiaoqian"></use></svg></div>SpringBoot</a></div></div><link rel="stylesheet" href="/css/coin.css" media="defer" onload="this.media='all'"/><div class="post-reward"><button class="tip-button reward-button"><span class="tip-button__text">投喂作者</span><div class="coin-wrapper"><div class="coin"><div class="coin__middle"></div><div class="coin__back"></div><div class="coin__front"></div></div></div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="https://www.naste.top:9000/images/wechat.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="https://www.naste.top:9000/images/wechat.jpg" alt="微信"/></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="https://www.naste.top:9000/images/alipay.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="https://www.naste.top:9000/images/alipay.jpg" alt="支付宝"/></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></button></div><audio id="coinAudio" src="https://npm.elemecdn.com/akilar-candyassets@1.0.36/audio/aowu.m4a"></audio><script defer="defer" src="/js/coin.js"></script><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/posts/4126800539.html"><img class="prev-cover" src= "" data-lazy-src="https://www.naste.top:9000/webp/1515952743776.webp" onerror="onerror=null;src='/assets/r2.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">Docker</div></div></a></div><div class="next-post pull-right"><a href="/posts/2100227203.html"><img class="next-cover" src= "" data-lazy-src="https://www.naste.top:9000/webp/1515952743791.webp" onerror="onerror=null;src='/assets/r2.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">SpringSecurity</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/posts/4265763703.html" title="使用Spring Session解决分布式Session共享问题"><img class="cover" src= "" data-lazy-src="https://www.naste.top:9000/webp/1671882661.webp" alt="cover"><div class="content is-center"><div class="date"><i class="fas fa-history fa-fw"></i> 2024-04-26</div><div class="title">使用Spring Session解决分布式Session共享问题</div></div></a></div><div><a href="/posts/3041119952.html" title="RabbitMQ"><img class="cover" src= "" data-lazy-src="https://www.naste.top:9000/webp/1678672812.webp" alt="cover"><div class="content is-center"><div class="date"><i class="fas fa-history fa-fw"></i> 2024-04-26</div><div class="title">RabbitMQ</div></div></a></div><div><a href="/posts/1154747761.html" title="代码生成器项目解读"><img class="cover" src= "" data-lazy-src="https://www.naste.top:9000/webp/1678368249.webp" alt="cover"><div class="content is-center"><div class="date"><i class="fas fa-history fa-fw"></i> 2024-04-26</div><div class="title">代码生成器项目解读</div></div></a></div><div><a href="/posts/2510331546.html" title="SpringBoot3响应式编程"><img class="cover" src= "" data-lazy-src="https://www.naste.top:9000/webp/1671882662.webp" alt="cover"><div class="content is-center"><div class="date"><i class="fas fa-history fa-fw"></i> 2024-04-26</div><div class="title">SpringBoot3响应式编程</div></div></a></div><div><a href="/posts/3528284937.html" title="SpringBoot自定义注解使用"><img class="cover" src= "" data-lazy-src="https://www.naste.top:9000/webp/1671882685.webp" alt="cover"><div class="content is-center"><div class="date"><i class="fas fa-history fa-fw"></i> 2024-04-26</div><div class="title">SpringBoot自定义注解使用</div></div></a></div><div><a href="/posts/1575856937.html" title="SpringBoot添加对LocalDateTime序列化"><img class="cover" src= "" data-lazy-src="https://www.naste.top:9000/webp/1671882661.webp" alt="cover"><div class="content is-center"><div class="date"><i class="fas fa-history fa-fw"></i> 2024-04-26</div><div class="title">SpringBoot添加对LocalDateTime序列化</div></div></a></div></div></div><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><svg class="meta_icon" style="width:22px;height:22px;position:relative;top:5px"><use xlink:href="#icon-mulu1"></use></svg><span style="font-weight:bold">目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#SpringBoot-%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8"><span class="toc-text">SpringBoot-基础入门</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81Spring%E4%B8%8ESpringBoot"><span class="toc-text">一、Spring与SpringBoot</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81Spring%E8%83%BD%E5%81%9A%E4%BB%80%E4%B9%88"><span class="toc-text">1、Spring能做什么</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1%E3%80%81Spring%E7%9A%84%E8%83%BD%E5%8A%9B"><span class="toc-text">1.1、Spring的能力</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2%E3%80%81Spring%E7%9A%84%E7%94%9F%E6%80%81"><span class="toc-text">1.2、Spring的生态</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3%E3%80%81Spring5%E7%9A%84%E9%87%8D%E5%A4%A7%E5%8D%87%E7%BA%A7"><span class="toc-text">1.3、Spring5的重大升级</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-3-1%E3%80%81%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B"><span class="toc-text">1.3.1、响应式编程</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1%E3%80%813%E3%80%812%E3%80%81%E5%86%85%E9%83%A8%E6%BA%90%E7%A0%81%E8%AE%BE%E8%AE%A1"><span class="toc-text">1、3、2、内部源码设计</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81%E4%B8%BA%E4%BB%80%E4%B9%88%E7%94%A8SpringBoot"><span class="toc-text">2、为什么用SpringBoot</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1%E3%80%81SpringBoot%E4%BC%98%E7%82%B9"><span class="toc-text">2.1、SpringBoot优点</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2%E3%80%81SpringBoot%E7%9A%84%E7%BC%BA%E7%82%B9"><span class="toc-text">2.2、SpringBoot的缺点</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3%E3%80%81%E6%97%B6%E4%BB%A3%E8%83%8C%E6%99%AF"><span class="toc-text">3、时代背景</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1"><span class="toc-text">3.1、微服务</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2%E3%80%81%E5%88%86%E5%B8%83%E5%BC%8F"><span class="toc-text">3.2、分布式</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#3-2-1%E3%80%81%E5%88%86%E5%B8%83%E5%BC%8F%E7%9A%84%E5%9B%B0%E9%9A%BE"><span class="toc-text">3.2.1、分布式的困难</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-2-2%E3%80%81%E5%88%86%E5%B8%83%E5%BC%8F%E7%9A%84%E8%A7%A3%E5%86%B3"><span class="toc-text">3.2.2、分布式的解决</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3%E3%80%81%E4%BA%91%E5%8E%9F%E7%94%9F"><span class="toc-text">3.3、云原生</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#3-3-1%E3%80%81%E4%B8%8A%E4%BA%91%E7%9A%84%E5%9B%B0%E9%9A%BE"><span class="toc-text">3.3.1、上云的困难</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-3-2%E3%80%81%E4%B8%8A%E4%BA%91%E7%9A%84%E8%A7%A3%E5%86%B3"><span class="toc-text">3.3.2、上云的解决</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4%E3%80%81%E5%A6%82%E4%BD%95%E5%AD%A6%E4%B9%A0SpringBoot"><span class="toc-text">4、如何学习SpringBoot</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-1%E3%80%81%E5%AE%98%E7%BD%91%E6%96%87%E6%A1%A3%E6%9E%B6%E6%9E%84"><span class="toc-text">4.1、官网文档架构</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2%E3%80%81%E6%9F%A5%E7%9C%8B%E7%89%88%E6%9C%AC%E6%96%B0%E7%89%B9%E6%80%A7"><span class="toc-text">4.2、查看版本新特性</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81SpringBoot%E5%85%A5%E9%97%A8"><span class="toc-text">二、SpringBoot入门</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81%E7%B3%BB%E7%BB%9F%E8%A6%81%E6%B1%82"><span class="toc-text">1、系统要求</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1%E3%80%81Maven%E8%AE%BE%E7%BD%AE"><span class="toc-text">1.1、Maven设置</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81%E7%AC%AC%E4%B8%80%E4%B8%AASpringBoot%E9%A1%B9%E7%9B%AE"><span class="toc-text">2、第一个SpringBoot项目</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1%E3%80%81%E5%88%9B%E5%BB%BAMaven%E9%A1%B9%E7%9B%AE"><span class="toc-text">2.1、创建Maven项目</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2%E3%80%81%E5%BC%95%E5%85%A5%E4%BE%9D%E8%B5%96"><span class="toc-text">2.2、引入依赖</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3%E3%80%81%E5%88%9B%E5%BB%BA%E4%B8%BB%E7%A8%8B%E5%BA%8F"><span class="toc-text">2.3、创建主程序</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-4%E3%80%81%E6%B5%8B%E8%AF%95"><span class="toc-text">2.4、测试</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-5%E3%80%81%E7%AE%80%E5%8C%96%E9%85%8D%E7%BD%AE"><span class="toc-text">2.5、简化配置</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-6%E3%80%81%E7%AE%80%E5%8C%96%E9%85%8D%E7%BD%AE"><span class="toc-text">2.6、简化配置</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%89%E3%80%81%E4%BA%86%E8%A7%A3%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E5%8E%9F%E7%90%86"><span class="toc-text">三、了解自动配置原理</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81SpringBoot%E7%89%B9%E7%82%B9"><span class="toc-text">1、SpringBoot特点</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1%E3%80%81%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86"><span class="toc-text">1.1、依赖管理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2%E3%80%81%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE"><span class="toc-text">1.2、自动配置</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81%E5%AE%B9%E5%99%A8%E7%BB%84%E4%BB%B6%E5%8A%9F%E8%83%BD"><span class="toc-text">2、容器组件功能</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1%E3%80%81%E7%BB%84%E4%BB%B6%E6%B7%BB%E5%8A%A0"><span class="toc-text">2.1、组件添加</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1-1%E3%80%81Configuration"><span class="toc-text">2.1.1、Configuration</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1-2%E3%80%81-Bean%E3%80%81-Component%E3%80%81-Controller%E3%80%81-Service%E3%80%81-Repository"><span class="toc-text">2.1.2、@Bean、@Component、@Controller、@Service、@Repository</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1-3%E3%80%81-ComponentScan%E3%80%81-Import"><span class="toc-text">2.1.3、@ComponentScan、@Import</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1-4%E3%80%81-Conditional"><span class="toc-text">2.1.4、@Conditional</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2%E3%80%81%E5%8E%9F%E7%94%9F%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%BC%95%E5%85%A5"><span class="toc-text">2.2、原生配置文件引入</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-2-1%E3%80%81-ImportResource"><span class="toc-text">2.2.1、@ImportResource</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3%E3%80%81properties%E9%85%8D%E7%BD%AE%E7%BB%91%E5%AE%9A"><span class="toc-text">2.3、properties配置绑定</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-3-1%E3%80%81-ConfigurationProperties-Component"><span class="toc-text">2.3.1、@ConfigurationProperties + @Component</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-3-2%E3%80%81-EnableConfigurationProperties-ConfigurationProperties"><span class="toc-text">2.3.2、@EnableConfigurationProperties + @ConfigurationProperties</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3%E3%80%81%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E5%8E%9F%E7%90%86%E5%85%A5%E9%97%A8"><span class="toc-text">3、自动配置原理入门</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1%E3%80%81%E5%BC%95%E5%AF%BC%E5%8A%A0%E8%BD%BD%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB"><span class="toc-text">3.1、引导加载自动配置类</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-1%E3%80%81-SpringBootConfiguration"><span class="toc-text">3.1.1、@SpringBootConfiguration</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-2%E3%80%81-ComponentScan"><span class="toc-text">3.1.2、@ComponentScan</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-3%E3%80%81-EnableAutoConfiguration"><span class="toc-text">3.1.3、@EnableAutoConfiguration</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2%E3%80%81%E6%8C%89%E9%9C%80%E5%BC%80%E5%90%AF%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E9%A1%B9"><span class="toc-text">3.2、按需开启自动配置项</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3%E3%80%81%E4%BF%AE%E6%94%B9%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE"><span class="toc-text">3.3、修改默认配置</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4%E3%80%81%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5"><span class="toc-text">3.4、最佳实践</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4%E3%80%81%E5%BC%80%E5%8F%91%E5%B0%8F%E6%8A%80%E5%B7%A7"><span class="toc-text">4、开发小技巧</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-1%E3%80%81Lombok"><span class="toc-text">4.1、Lombok</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2%E3%80%81dev-tools"><span class="toc-text">4.2、dev-tools</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-3%E3%80%81Spring-Initailizr%EF%BC%88%E9%A1%B9%E7%9B%AE%E5%88%9D%E5%A7%8B%E5%8C%96%E5%90%91%E5%AF%BC%EF%BC%89"><span class="toc-text">4.3、Spring Initailizr（项目初始化向导）</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#SpringBoot-%E6%A0%B8%E5%BF%83%E5%8A%9F%E8%83%BD"><span class="toc-text">SpringBoot-核心功能</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="toc-text">一、配置文件</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B"><span class="toc-text">1、文件类型</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1%E3%80%81properties"><span class="toc-text">1.1、properties</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2%E3%80%81yaml"><span class="toc-text">1.2、yaml</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2-1%E3%80%81%E7%AE%80%E4%BB%8B"><span class="toc-text">1.2.1、简介</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2-2%E3%80%81%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95"><span class="toc-text">1.2.2、基本语法</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2-3%E3%80%81%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B"><span class="toc-text">1.2.3、数据类型</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2-4%E3%80%81%E5%AE%9E%E4%BE%8B"><span class="toc-text">1.2.4、实例</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3%E3%80%81%E7%BC%96%E5%86%99yaml%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E6%8F%90%E7%A4%BA%E9%97%AE%E9%A2%98"><span class="toc-text">1.3、编写yaml配置文件提示问题</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-4%E3%80%81%E6%B3%A8%E6%84%8F"><span class="toc-text">1.4、注意</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81web%E5%BC%80%E5%8F%91"><span class="toc-text">二、web开发</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81SpringMVC%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E6%A6%82%E8%A7%88"><span class="toc-text">1、SpringMVC自动配置概览</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81%E7%AE%80%E5%8D%95%E5%8A%9F%E8%83%BD%E5%88%86%E6%9E%90"><span class="toc-text">2、简单功能分析</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1%E3%80%81%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E8%AE%BF%E9%97%AE"><span class="toc-text">2.1、静态资源访问</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1%E3%80%81%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E9%BB%98%E8%AE%A4%E7%9B%AE%E5%BD%95"><span class="toc-text">2.1、静态资源默认目录</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-2%E3%80%81%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E8%AE%BF%E9%97%AE%E5%89%8D%E7%BC%80"><span class="toc-text">2.2、静态资源访问前缀</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-3%E3%80%81%E4%BF%AE%E6%94%B9%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E7%9A%84%E9%BB%98%E8%AE%A4%E7%9B%AE%E5%BD%95"><span class="toc-text">2.3、修改静态资源的默认目录</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-4%E3%80%81WebJars"><span class="toc-text">2.4、WebJars</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2%E3%80%81%E6%AC%A2%E8%BF%8E%E9%A1%B5%E6%94%AF%E6%8C%81"><span class="toc-text">2.2、欢迎页支持</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3%E3%80%81%E8%87%AA%E5%AE%9A%E4%B9%89-Favicon"><span class="toc-text">2.3、自定义 Favicon</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-4%E3%80%81%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E9%85%8D%E7%BD%AE%E5%8E%9F%E7%90%86"><span class="toc-text">2,4、静态资源配置原理</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3%E3%80%81%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E5%A4%84%E7%90%86"><span class="toc-text">3、请求参数处理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1%E8%AF%B7%E6%B1%82%E6%98%A0%E5%B0%84"><span class="toc-text">3.1请求映射</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-1%E3%80%81rest%E4%BD%BF%E7%94%A8%E4%B8%8E%E5%8E%9F%E7%90%86"><span class="toc-text">3.1.1、rest使用与原理</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-2%E3%80%81%E8%87%AA%E5%AE%9A%E4%B9%89Rest%E6%8B%A6%E6%88%AA%E5%99%A8"><span class="toc-text">3.1.2、自定义Rest拦截器</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-3%E3%80%81%E8%AF%B7%E6%B1%82%E6%98%A0%E5%B0%84%E5%8E%9F%E7%90%86"><span class="toc-text">3.1.3、请求映射原理</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2%E3%80%81%E6%99%AE%E9%80%9A%E5%8F%82%E6%95%B0%E4%B8%8E%E5%9F%BA%E6%9C%AC%E6%B3%A8%E8%A7%A3"><span class="toc-text">3.2、普通参数与基本注解</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#3-2-1%E3%80%81%E6%B3%A8%E8%A7%A3"><span class="toc-text">3.2.1、注解</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-2-2%E3%80%81Servlet-API"><span class="toc-text">3.2.2、Servlet API</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-2-3%E3%80%81%E5%A4%8D%E6%9D%82%E5%8F%82%E6%95%B0"><span class="toc-text">3.2.3、复杂参数</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-2-4%E3%80%81%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E5%8F%82%E6%95%B0"><span class="toc-text">3.2.4、自定义对象参数</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3%E3%80%81POJO%E5%B0%81%E8%A3%85%E8%BF%87%E7%A8%8B"><span class="toc-text">3.3、POJO封装过程</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4%E3%80%81%E5%8F%82%E6%95%B0%E5%A4%84%E7%90%86%E5%8E%9F%E7%90%86"><span class="toc-text">3.4、参数处理原理</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4%E3%80%81%E6%95%B0%E6%8D%AE%E5%93%8D%E5%BA%94%E4%B8%8E%E5%86%85%E5%AE%B9%E5%8D%8F%E5%95%86"><span class="toc-text">4、数据响应与内容协商</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5%E3%80%81%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90%E4%B8%8E%E6%A8%A1%E6%9D%BF%E5%BC%95%E6%93%8E"><span class="toc-text">5、视图解析与模板引擎</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#5-1%E3%80%81%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90"><span class="toc-text">5.1、视图解析</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#5-1-1%E3%80%81%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90%E5%8E%9F%E7%90%86%E6%B5%81%E7%A8%8B"><span class="toc-text">5.1.1、视图解析原理流程</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-2%E3%80%81%E6%A8%A1%E6%9D%BF%E5%BC%95%E6%93%8E-Thymeleaf"><span class="toc-text">5.2、模板引擎-Thymeleaf</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#5-2-1%E3%80%81Thymeleaf%E7%AE%80%E4%BB%8B"><span class="toc-text">5.2.1、Thymeleaf简介</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-2-2%E3%80%81%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95"><span class="toc-text">5.2.2、基本语法</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#5-2-1-1%E3%80%81%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="toc-text">5.2.1.1、表达式</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#5-2-1-2%E3%80%81%E5%AD%97%E9%9D%A2%E9%87%8F"><span class="toc-text">5.2.1.2、字面量</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#5-2-1-3%E3%80%81%E6%96%87%E6%9C%AC%E6%93%8D%E4%BD%9C"><span class="toc-text">5.2.1.3、文本操作</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#5-2-1-4%E3%80%81%E6%95%B0%E5%AD%A6%E8%BF%90%E7%AE%97"><span class="toc-text">5.2.1.4、数学运算</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#5-2-1-5%E3%80%81%E5%B8%83%E5%B0%94%E8%BF%90%E7%AE%97"><span class="toc-text">5.2.1.5、布尔运算</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#5-2-1-6%E3%80%81%E6%AF%94%E8%BE%83%E8%BF%90%E7%AE%97"><span class="toc-text">5.2.1.6、比较运算</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#5-2-1-7%E3%80%81%E6%9D%A1%E4%BB%B6%E8%BF%90%E7%AE%97"><span class="toc-text">5.2.1.7、条件运算</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#5-2-1-8%E3%80%81%E7%89%B9%E6%AE%8A%E6%93%8D%E4%BD%9C"><span class="toc-text">5.2.1.8、特殊操作</span></a></li></ol></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-2-3%E3%80%81%E8%AE%BE%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%80%BC-th-attr"><span class="toc-text">5.2.3、设置属性值-th:attr</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-2-4%E3%80%81%E8%BF%AD%E4%BB%A3"><span class="toc-text">5.2.4、迭代</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-2-5%E3%80%81%E6%9D%A1%E4%BB%B6%E8%BF%90%E7%AE%97"><span class="toc-text">5.2.5、条件运算</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-2-6%E3%80%81%E5%B1%9E%E6%80%A7%E4%BC%98%E5%85%88%E7%BA%A7"><span class="toc-text">5.2.6、属性优先级</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-3%E3%80%81Thymeleaf%E4%BD%BF%E7%94%A8"><span class="toc-text">5.3、Thymeleaf使用</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#5-3-1%E3%80%81%E5%BC%95%E5%85%A5Thymeleaf"><span class="toc-text">5.3.1、引入Thymeleaf</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-3-2%E3%80%81%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AEthymeleaf"><span class="toc-text">5.3.2、自动配置thymeleaf</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-3-3%E3%80%81%E9%A1%B5%E9%9D%A2%E5%BC%80%E5%8F%91"><span class="toc-text">5.3.3、页面开发</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-4%E3%80%81%E6%9E%84%E5%BB%BA%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F"><span class="toc-text">5.4、构建后台管理系统</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#5-4-1%E3%80%81%E9%A1%B9%E7%9B%AE%E5%88%9B%E5%BB%BA"><span class="toc-text">5.4.1、项目创建</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-4-2%E3%80%81%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E5%A4%84%E7%90%86"><span class="toc-text">5.4.2、静态资源处理</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-4-3%E3%80%81%E8%B7%AF%E5%BE%84%E6%9E%84%E5%BB%BA"><span class="toc-text">5.4.3、路径构建</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-4-4%E3%80%81%E6%A8%A1%E6%9D%BF%E6%8A%BD%E5%8F%96"><span class="toc-text">5.4.4、模板抽取</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-4-5%E3%80%81%E9%A1%B5%E9%9D%A2%E8%B7%B3%E8%BD%AC"><span class="toc-text">5.4.5、页面跳转</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#5-4-6%E3%80%81%E6%95%B0%E6%8D%AE%E6%B8%B2%E6%9F%93"><span class="toc-text">5.4.6、数据渲染</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6%E3%80%81%E6%8B%A6%E6%88%AA%E5%99%A8"><span class="toc-text">6、拦截器</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#6-1%E3%80%81%E9%85%8D%E7%BD%AE%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8B%A6%E6%88%AA%E5%99%A8"><span class="toc-text">6.1、配置自定义拦截器</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-2%E3%80%81%E6%B3%A8%E5%86%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8B%A6%E6%88%AA%E5%99%A8"><span class="toc-text">6.2、注册自定义拦截器</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-3%E3%80%81%E6%8B%A6%E6%88%AA%E5%99%A8%E5%8E%9F%E7%90%86"><span class="toc-text">6.3、拦截器原理</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7%E3%80%81%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0"><span class="toc-text">7、文件上传</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1%E3%80%81%E8%A1%A8%E5%8D%95%E9%A1%B5%E9%9D%A2"><span class="toc-text">1、表单页面</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2%E3%80%81%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E4%BB%A3%E7%A0%81"><span class="toc-text">2、文件上传代码</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3%E3%80%81%E4%BF%AE%E6%94%B9%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="toc-text">3、修改文件上传配置文件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4%E3%80%81%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E5%8E%9F%E7%90%86"><span class="toc-text">4、文件上传自动配置原理</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#8%E3%80%81%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86"><span class="toc-text">8、异常处理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1%E3%80%81%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86"><span class="toc-text">8.1、错误处理</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#8-1-1%E3%80%81%E9%BB%98%E8%AE%A4%E8%A7%84%E5%88%99"><span class="toc-text">8.1.1、默认规则</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#8-1-2%E3%80%81%E5%AE%9A%E5%88%B6%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86%E9%80%BB%E8%BE%91"><span class="toc-text">8.1.2、定制错误处理逻辑</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#8-1-3%E3%80%81%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E5%8E%9F%E7%90%86"><span class="toc-text">8.1.3、异常处理自动配置原理</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#8-1-4%E3%80%81%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E6%AD%A5%E9%AA%A4%E6%B5%81%E7%A8%8B"><span class="toc-text">8.1.4、异常处理步骤流程</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9%E3%80%81Web%E5%8E%9F%E7%94%9F%E7%BB%84%E4%BB%B6%E6%B3%A8%E5%85%A5%EF%BC%88Servlet%E3%80%81Filter%E3%80%81Listener%EF%BC%89"><span class="toc-text">9、Web原生组件注入（Servlet、Filter、Listener）</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#9-1%E3%80%81%E4%BD%BF%E7%94%A8Servlet-API"><span class="toc-text">9.1、使用Servlet API</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-2%E3%80%81%E4%BD%BF%E7%94%A8-ServletComponentScan%E6%B3%A8%E5%86%8CServlet%E7%BB%84%E4%BB%B6"><span class="toc-text">9.2、使用@ServletComponentScan注册Servlet组件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-3%E3%80%81%E4%BD%BF%E7%94%A8RegistrationBean%E6%B3%A8%E5%86%8CServlet%E7%BB%84%E4%BB%B6"><span class="toc-text">9.3、使用RegistrationBean注册Servlet组件</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#10%E3%80%81%E5%B5%8C%E5%85%A5%E5%BC%8FServlet%E5%AE%B9%E5%99%A8"><span class="toc-text">10、嵌入式Servlet容器</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#11%E3%80%81%E5%AE%9A%E5%88%B6%E5%8C%96%E5%8E%9F%E7%90%86"><span class="toc-text">11、定制化原理</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#11-1%E3%80%81%E5%AE%9A%E5%88%B6%E5%8C%96%E7%9A%84%E5%B8%B8%E8%A7%81%E6%96%B9%E5%BC%8F"><span class="toc-text">11.1、定制化的常见方式</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#11-2%E3%80%81%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90"><span class="toc-text">11.2、原理分析</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%89%E3%80%81%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%EF%BC%88%E6%93%8D%E4%BD%9C%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%89"><span class="toc-text">三、数据访问（操作数据库）</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81SQL"><span class="toc-text">1、SQL</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1%E3%80%81%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE-HikariDataSource"><span class="toc-text">1.1、数据源的自动配置-HikariDataSource</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-1-1%E3%80%81%E5%AF%BC%E5%85%A5JDBC%E5%9C%BA%E6%99%AF"><span class="toc-text">1.1.1、导入JDBC场景</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-1-2%E3%80%81%E5%88%86%E6%9E%90%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE"><span class="toc-text">1.1.2、分析自动配置</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#1%E3%80%81%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%9A%84%E7%B1%BB"><span class="toc-text">1、自动配置的类</span></a></li></ol></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-3%E3%80%81%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE%E9%A1%B9"><span class="toc-text">3.1.3、修改配置项</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-4%E3%80%81%E6%B5%8B%E8%AF%95"><span class="toc-text">3.1.4、测试</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2%E3%80%81%E4%BD%BF%E7%94%A8Druid%E6%95%B0%E6%8D%AE%E6%BA%90"><span class="toc-text">1.2、使用Druid数据源</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2-1%E3%80%81Druid%E7%9A%84GitHub%E5%9C%B0%E5%9D%80"><span class="toc-text">1.2.1、Druid的GitHub地址</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2-2%E3%80%81SpringBoot%E6%95%B4%E5%90%88Druid"><span class="toc-text">1.2.2、SpringBoot整合Druid</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2-3%E3%80%81%E8%87%AA%E5%AE%9A%E4%B9%89%E6%96%B9%E5%BC%8F"><span class="toc-text">1.2.3、自定义方式</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#1-2-3-1%E3%80%81%E5%88%9B%E5%BB%BA%E6%95%B0%E6%8D%AE%E6%BA%90"><span class="toc-text">1.2.3.1、创建数据源</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#1-2-3-2%E3%80%81StatViewServlet"><span class="toc-text">1.2.3.2、StatViewServlet</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#1-2-3-3%E3%80%81StatFilter"><span class="toc-text">1.2.3.3、StatFilter</span></a></li></ol></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2-4%E3%80%81%E4%BD%BF%E7%94%A8%E5%AE%98%E6%96%B9starter%E6%96%B9%E5%BC%8F"><span class="toc-text">1.2.4、使用官方starter方式</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#1-2-4-1%E3%80%81%E5%BC%95%E5%85%A5druid-stater"><span class="toc-text">1.2.4.1、引入druid-stater</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#1-2-4-2%E3%80%81%E5%88%86%E6%9E%90%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE"><span class="toc-text">1.2.4.2、分析自动配置</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#1-2-4-3%E3%80%81%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B"><span class="toc-text">1.2.4.3、配置示例</span></a></li></ol></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3%E3%80%81%E6%95%B4%E5%90%88MyBatis"><span class="toc-text">1.3、整合MyBatis</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-3-1%E3%80%81%E9%85%8D%E7%BD%AE%E6%A8%A1%E5%BC%8F"><span class="toc-text">1.3.1、配置模式</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-3-2%E3%80%81%E6%B3%A8%E8%A7%A3%E6%A8%A1%E5%BC%8F"><span class="toc-text">1.3.2、注解模式</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-3-3%E3%80%81%E6%B7%B7%E5%90%88%E6%A8%A1%E5%BC%8F"><span class="toc-text">1.3.3、混合模式</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-3-4%E3%80%81%E6%80%BB%E7%BB%93"><span class="toc-text">1.3.4、总结</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-4%E3%80%81%E6%95%B4%E5%90%88MyBatisPlus"><span class="toc-text">1.4、整合MyBatisPlus</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-4-1%E3%80%81%E6%95%B4%E5%90%88MyBatisPlus"><span class="toc-text">1.4.1、整合MyBatisPlus</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-4-2%E3%80%81MP%E7%9A%84%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE"><span class="toc-text">1.4.2、MP的自动配置</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-4-3%E3%80%81%E4%BC%98%E7%82%B9%EF%BC%9A"><span class="toc-text">1.4.3、优点：</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-4-4%E3%80%81%E7%AE%80%E5%8D%95CRUD"><span class="toc-text">1.4.4、简单CRUD</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-5%E3%80%81%E6%95%B4%E5%90%88PageHelper%E6%8F%92%E4%BB%B6"><span class="toc-text">1.5、整合PageHelper插件</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-5-1%E3%80%81%E5%BC%95%E5%85%A5Starter"><span class="toc-text">1.5.1、引入Starter</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-5-2%E3%80%81%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%EF%BC%9A"><span class="toc-text">1.5.2、简单使用：</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9B%9B%E3%80%81%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95"><span class="toc-text">四、单元测试</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81Junit5%E5%8F%98%E5%8C%96"><span class="toc-text">1、Junit5变化</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81JUnit5%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3"><span class="toc-text">2、JUnit5常用注解</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3%E3%80%81%E6%96%AD%E8%A8%80%EF%BC%88assertions%EF%BC%89"><span class="toc-text">3、断言（assertions）</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1%E3%80%81%E7%AE%80%E5%8D%95%E6%96%AD%E8%A8%80"><span class="toc-text">3.1、简单断言</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2%E3%80%81%E6%95%B0%E7%BB%84%E6%96%AD%E8%A8%80"><span class="toc-text">3.2、数组断言</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3%E3%80%81%E7%BB%84%E5%90%88%E6%96%AD%E8%A8%80"><span class="toc-text">3.3、组合断言</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4%E3%80%81%E5%BC%82%E5%B8%B8%E6%96%AD%E8%A8%80"><span class="toc-text">3.4、异常断言</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-5%E3%80%81%E8%B6%85%E6%97%B6%E6%96%AD%E8%A8%80"><span class="toc-text">3.5、超时断言</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-6%E3%80%81%E5%BF%AB%E9%80%9F%E5%A4%B1%E8%B4%A5"><span class="toc-text">3.6、快速失败</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4%E3%80%81%E5%89%8D%E7%BD%AE%E6%9D%A1%E4%BB%B6"><span class="toc-text">4、前置条件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5%E3%80%81%E5%B5%8C%E5%A5%97%E6%B5%8B%E8%AF%95"><span class="toc-text">5、嵌套测试</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6%E3%80%81%E5%8F%82%E6%95%B0%E5%8C%96%E6%B5%8B%E8%AF%95"><span class="toc-text">6、参数化测试</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7%E3%80%81Junit4%E8%BF%81%E7%A7%BB%E5%88%B0Junit5%E6%8C%87%E5%8D%97"><span class="toc-text">7、Junit4迁移到Junit5指南</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%94%E3%80%81%E6%8C%87%E6%A0%87%E7%9B%91%E6%8E%A7"><span class="toc-text">五、指标监控</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81SpringBoot-Actuator"><span class="toc-text">1、SpringBoot Actuator</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1%E3%80%81%E7%AE%80%E4%BB%8B"><span class="toc-text">1.1、简介</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2%E3%80%811-x%E4%B8%8E2-x%E7%9A%84%E4%B8%8D%E5%90%8C"><span class="toc-text">1.2、1.x与2.x的不同</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3%E3%80%81%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8"><span class="toc-text">1.3、如何使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-4%E3%80%81%E5%8F%AF%E8%A7%86%E5%8C%96"><span class="toc-text">1.4、可视化</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81Actuator-Endpoint"><span class="toc-text">2、Actuator Endpoint</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1%E3%80%81%E6%9C%80%E5%B8%B8%E4%BD%BF%E7%94%A8%E7%9A%84%E7%AB%AF%E7%82%B9"><span class="toc-text">2.1、最常使用的端点</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%AD%E3%80%81%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90"><span class="toc-text">六、原理解析</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98"><span class="toc-text">跨域问题</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81%E5%9C%A8SpringBoot%E4%B8%AD%E8%A7%A3%E5%86%B3%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98"><span class="toc-text">一、在SpringBoot中解决跨域问题</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E8%B7%A8%E5%9F%9F%E7%9A%84%E6%97%B6%E5%80%99%E7%BB%91%E5%AE%9ACookie%E5%87%BA%E7%8E%B0%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-text">二、跨域的时候绑定Cookie出现的问题</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#SpringBoot%E6%95%B4%E5%90%88Vue%E4%B8%AD%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-text">SpringBoot整合Vue中的问题</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81Cookie%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-text">1、Cookie的问题</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93%E9%97%AE%E9%A2%98"><span class="toc-text">2、数据库问题</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81%E6%97%A5%E6%9C%9F%E6%A0%BC%E5%BC%8F%E5%8C%96%E9%97%AE%E9%A2%98"><span class="toc-text">3、日期格式化问题</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4%E3%80%81SpringBoot%E6%8B%A6%E6%88%AA%E5%99%A8%E8%8E%B7%E5%8F%96%E4%B8%8D%E5%88%B0Session%E7%9A%84%E5%80%BC"><span class="toc-text">4、SpringBoot拦截器获取不到Session的值</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Vue%E4%BD%BF%E7%94%A8%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-text">Vue使用遇到的问题</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81%E7%82%B9%E5%87%BB%E4%BA%8B%E4%BB%B6"><span class="toc-text">一、点击事件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E6%8B%A6%E6%88%AA%E4%BA%8B%E4%BB%B6"><span class="toc-text">二、拦截事件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%89%E3%80%81%E4%BD%BF%E7%94%A8Vue%E8%BF%9B%E8%A1%8C%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0"><span class="toc-text">三、使用Vue进行文件上传</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%89%E3%80%81axios%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="toc-text">三、axios的使用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81%E5%9C%A8axios%E4%B8%AD%EF%BC%8Cparam%E5%92%8Cdata%E5%B1%9E%E6%80%A7%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-text">1、在axios中，param和data属性的区别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81%E4%BD%BF%E7%94%A8axios%E4%BC%A0%E5%8F%82%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-text">2、使用axios传参的问题</span></a></li></ol></li></ol></div></div></div></div></main><footer id="footer" style="background-color: transparent;"><div id="footer-wrap"><div id="ft"><div class="ft-item-1"><div class="t-top"><div class="t-t-l"><p class="ft-t t-l-t">格言🧬</p><div class="bg-ad"><div>再看看那个光点，它就在这里，这是家园，这是我们 —— 你所爱的每一个人，你认识的一个人，你听说过的每一个人，曾经有过的每一个人，都在它上面度过他们的一生✨</div><div class="btn-xz-box"><a class="btn-xz" target="_blank" rel="noopener" href="https://stellarium.org/">点击开启星辰之旅</a></div></div></div><div class="t-t-r"><p class="ft-t t-l-t">猜你想看💡</p><ul class="ft-links"><li><a href="/posts/eec9786.html">魔改指南</a><a href="/box/nav/">网址导航</a></li><li><a href="/social/link/">我的朋友</a><a href="/comments/">留点什么</a></li><li><a href="/personal/about/">关于作者</a><a href="/archives/">文章归档</a></li><li><a href="/categories/">文章分类</a><a href="/tags/">文章标签</a></li><li><a href="/box/Gallery/">我的画廊</a><a href="/personal/bb/">我的唠叨</a></li><li><a href="/site/time/">建设进程</a><a href="/site/census/">网站统计</a></li></ul></div></div></div><div class="ft-item-2"><p class="ft-t">推荐友链⌛</p><div class="ft-img-group"><div class="img-group-item"><a href="https://www.naste.top:1024/" title="XiaoFei🥝"><img src= "" data-lazy-src="https://www.naste.top:9000/images/cat.jpg" alt=""/></a></div><div class="img-group-item"><a href="javascript:void(0)" title="广告位招租"><img src= "" data-lazy-src="https://www.naste.top:9000/webp/65307a5828af6790.webp" alt=""/></a></div><div class="img-group-item"><a href="javascript:void(0)" title="广告位招租"><img src= "" data-lazy-src="https://www.naste.top:9000/webp/65307a5828af6790.webp" alt=""/></a></div><div class="img-group-item"><a href="javascript:void(0)" title="广告位招租"><img src= "" data-lazy-src="https://www.naste.top:9000/webp/65307a5828af6790.webp" alt=""/></a></div><div class="img-group-item"><a href="javascript:void(0)" title="广告位招租"><img src= "" data-lazy-src="https://www.naste.top:9000/webp/65307a5828af6790.webp" alt=""/></a></div><div class="img-group-item"><a href="javascript:void(0)" title="广告位招租"><img src= "" data-lazy-src="https://www.naste.top:9000/webp/65307a5828af6790.webp" alt=""/></a></div><div class="img-group-item"><a href="javascript:void(0)" title="广告位招租"><img src= "" data-lazy-src="https://www.naste.top:9000/webp/65307a5828af6790.webp" alt=""/></a></div><div class="img-group-item"><a href="javascript:void(0)" title="广告位招租"><img src= "" data-lazy-src="https://www.naste.top:9000/webp/65307a5828af6790.webp" alt=""/></a></div></div></div></div><div class="copyright"><span><b>&copy;2022-2024</b></span><span><b>&nbsp;&nbsp;By XiaoFei🥝</b></span></div><div id="workboard"></div><p id="ghbdages"><a class="github-badge" target="_blank" href="https://hexo.io/" style="margin-inline:5px" title="博客框架为Hexo_v6.3.0"><img src= "" data-lazy-src="https://static.naste.top:1024/svg/blog/Frame-Hexo-blue.svg" alt=""/></a><a class="github-badge" target="_blank" href="https://butterfly.js.org/" style="margin-inline:5px" title="主题版本Butterfly_v4.3.1"><img src= "" data-lazy-src="https://static.naste.top:1024/svg/blog/Theme-Butterfly-6513df.svg" alt=""/></a><a class="github-badge" target="_blank" href="https://vercel.com/" style="margin-inline:5px" title="本站采用多线部署，主线路托管于Vercel"><img src= "" data-lazy-src="https://static.naste.top:1024/svg/blog/Hosted-Vercel-brightgreen.svg" alt=""/></a><a class="github-badge" target="_blank" href="https://user.51.la/" style="margin-inline:5px" title="本站数据分析得益于51la技术支持"><img src= "" data-lazy-src="https://static.naste.top:1024/svg/blog/Analytics-51la-3db1eb.svg" alt=""/></a><a class="github-badge" target="_blank" href="https://github.com/" style="margin-inline:5px" title="本网站源码由Github提供存储仓库"><img src= "" data-lazy-src=" https://static.naste.top:1024/svg/blog/Source-Github-d021d6.svg" alt=""/></a></p></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><a class="icon-V hidden" onclick="switchNightMode()" title="浅色和深色模式转换"><svg width="25" height="25" viewBox="0 0 1024 1024"><use id="modeicon" xlink:href="#icon-moon"></use></svg></a><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button><button class="share" type="button" title="右键模式" onclick="changeMouseMode()"><i class="fas fa-mouse"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog right_side"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button class="share" type="button" title="分享链接" onclick="share()"><i class="fas fa-share-nodes"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i><span id="percent">0<span>%</span></span></button><button id="go-down" type="button" title="直达底部" onclick="btf.scrollToDest(document.body.scrollHeight, 500)"><i class="fas fa-arrow-down"></i></button></div></div><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div></div></div><div id="search-mask"></div></div><div class="js-pjax" id="rightMenu"><div class="rightMenu-group rightMenu-small"><a class="rightMenu-item" href="javascript:window.history.back();"><i class="fa fa-arrow-left"></i></a><a class="rightMenu-item" href="javascript:window.history.forward();"><i class="fa fa-arrow-right"></i></a><a class="rightMenu-item" href="javascript:window.location.reload();"><i class="fa fa-refresh"></i></a><a class="rightMenu-item" href="javascript:rmf.scrollToTop();"><i class="fa fa-arrow-up"></i></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-text"><a class="rightMenu-item" href="javascript:rmf.copySelect();"><i class="fa fa-copy"></i><span>复制</span></a><a class="rightMenu-item" href="javascript:window.open(&quot;https://www.baidu.com/s?wd=&quot;+window.getSelection().toString());window.location.reload();"><i class="fa fa-search"></i><span>百度搜索</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-too"><a class="rightMenu-item" href="javascript:window.open(window.getSelection().toString());window.location.reload();"><i class="fa fa-link"></i><span>转到链接</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-paste"><a class="rightMenu-item" href="javascript:rmf.paste()"><i class="fa fa-copy"></i><span>粘贴</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-post"><a class="rightMenu-item" href="#post-comment"><i class="fas fa-comment"></i><span>空降评论</span></a><a class="rightMenu-item" href="javascript:rmf.copyWordsLink()"><i class="fa fa-link"></i><span>复制本文地址</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-to"><a class="rightMenu-item" href="javascript:rmf.openWithNewTab()"><i class="fa fa-window-restore"></i><span>新窗口打开</span></a><a class="rightMenu-item" id="menu-too" href="javascript:rmf.open()"><i class="fa fa-link"></i><span>转到链接</span></a><a class="rightMenu-item" href="javascript:rmf.copyLink()"><i class="fa fa-copy"></i><span>复制链接</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-img"><a class="rightMenu-item" href="javascript:rmf.saveAs()"><i class="fa fa-download"></i><span>保存图片</span></a><a class="rightMenu-item" href="javascript:rmf.openWithNewTab()"><i class="fa fa-window-restore"></i><span>在新窗口打开</span></a><a class="rightMenu-item" href="javascript:rmf.copyLink()"><i class="fa fa-copy"></i><span>复制图片链接</span></a></div><div class="rightMenu-group rightMenu-line"><a class="rightMenu-item" href="javascript:randomPost()"><i class="fa fa-paper-plane"></i><span>随便逛逛</span></a><a class="rightMenu-item" href="javascript:switchNightMode();"><i class="fa fa-moon"></i><span>昼夜切换</span></a><a class="rightMenu-item" href="/personal/about/"><i class="fa fa-info-circle"></i><span>关于博客</span></a><a class="rightMenu-item" href="javascript:toggleWinbox();"><i class="fas fa-cog"></i><span>美化设置</span></a><a class="rightMenu-item" href="javascript:rmf.fullScreen();"><i class="fas fa-expand"></i><span>切换全屏</span></a><a class="rightMenu-item" href="javascript:window.print();"><i class="fa-solid fa-print"></i><span>打印页面</span></a></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.staticfile.org/fancyapps-ui/4.0.31/fancybox.umd.min.js"></script><script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/instant.page/5.1.0/instantpage.min.js" type="module"></script><script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vanilla-lazyload/17.3.1/lazyload.iife.min.js"></script><script>function panguFn () {
  if (typeof pangu === 'object') pangu.autoSpacingPage()
  else {
    getScript('https://cdnjs.cloudflare.com/ajax/libs/pangu/4.0.7/pangu.min.js')
      .then(() => {
        pangu.autoSpacingPage()
      })
  }
}

function panguInit () {
  if (true){
    GLOBAL_CONFIG_SITE.isPost && panguFn()
  } else {
    panguFn()
  }
}

document.addEventListener('DOMContentLoaded', panguInit)</script><script src="/js/search/local-search.js"></script><script async="async">var preloader = {
  endLoading: () => {
    document.body.style.overflow = 'auto';
    document.getElementById('loading-box').classList.add("loaded")
  },
  initLoading: () => {
    document.body.style.overflow = '';
    document.getElementById('loading-box').classList.remove("loaded")

  }
}
window.addEventListener('load',preloader.endLoading())
setTimeout(function(){preloader.endLoading();}, 5000);
document.getElementById('loading-box').addEventListener('click',()=> {preloader.endLoading()})</script><div class="js-pjax"><script>(()=>{
  const init = () => {
    twikoo.init(Object.assign({
      el: '#twikoo-wrap',
      envId: '',
      region: '',
      onCommentLoaded: function () {
        btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)'))
      }
    }, null))
  }

  const getCount = () => {
    const countELement = document.getElementById('twikoo-count')
    if(!countELement) return
    twikoo.getCommentsCount({
      envId: '',
      region: '',
      urls: [window.location.pathname],
      includeReply: false
    }).then(function (res) {
      countELement.innerText = res[0].count
    }).catch(function (err) {
      console.error(err);
    });
  }

  const runFn = () => {
    init()
    
  }

  const loadTwikoo = () => {
    if (typeof twikoo === 'object') {
      setTimeout(runFn,0)
      return
    } 
    getScript('https://cdn.staticfile.org/twikoo/1.6.8/twikoo.all.min.js').then(runFn)
  }

  if ('Twikoo' === 'Twikoo' || !true) {
    if (true) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo)
    else loadTwikoo()
  } else {
    window.loadOtherComment = () => {
      loadTwikoo()
    }
  }
})()</script></div><script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.min.js"></script><script async src="https://cdn1.tianli0.top/npm/vue@2.6.14/dist/vue.min.js"></script><script async src="https://cdn1.tianli0.top/npm/element-ui@2.15.6/lib/index.js"></script><script async src="https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script><script defer type="text/javascript" src="https://cdn1.tianli0.top/npm/sweetalert2@8.19.0/dist/sweetalert2.all.js"></script><script async src="//npm.elemecdn.com/pace-js@1.2.4/pace.min.js"></script><script defer src="https://cdn1.tianli0.top/gh/nextapps-de/winbox/dist/winbox.bundle.min.js"></script><script async src="//at.alicdn.com/t/c/font_3586335_hsivh70x0fm.js"></script><script async src="//at.alicdn.com/t/c/font_3636804_gr02jmjr3y9.js"></script><script async src="//at.alicdn.com/t/c/font_3612150_kfv55xn3u2g.js"></script><script async src="https://cdn.wpon.cn/2022-sucai/Gold-ingot.js"></script><canvas id="universe"></canvas><canvas id="snow"></canvas><script defer src="/js/fomal.js"></script><link rel="stylesheet" href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.js"></script><script src="https://cdn1.tianli0.top/npm/js-heo@1.0.12/metingjs/Meting.min.js"></script><script src="https://lib.baomitu.com/pjax/0.2.8/pjax.min.js"></script><script>let pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show","#web_bg",".js-pjax","#bibi","body > title","#app","#tag-echarts","#posts-echart","#categories-echarts"]

var pjax = new Pjax({
  elements: 'a:not([target="_blank"])',
  selectors: pjaxSelectors,
  cacheBust: false,
  analytics: false,
  scrollRestoration: false
})

document.addEventListener('pjax:send', function () {

  // removeEventListener scroll 
  window.tocScrollFn && window.removeEventListener('scroll', window.tocScrollFn)
  window.scrollCollect && window.removeEventListener('scroll', scrollCollect)

  typeof preloader === 'object' && preloader.initLoading()
  document.getElementById('rightside').style.cssText = "opacity: ''; transform: ''"
  
  if (window.aplayers) {
    for (let i = 0; i < window.aplayers.length; i++) {
      if (!window.aplayers[i].options.fixed) {
        window.aplayers[i].destroy()
      }
    }
  }

  typeof typed === 'object' && typed.destroy()

  //reset readmode
  const $bodyClassList = document.body.classList
  $bodyClassList.contains('read-mode') && $bodyClassList.remove('read-mode')

  typeof disqusjs === 'object' && disqusjs.destroy()
})

document.addEventListener('pjax:complete', function () {
  window.refreshFn()

  document.querySelectorAll('script[data-pjax]').forEach(item => {
    const newScript = document.createElement('script')
    const content = item.text || item.textContent || item.innerHTML || ""
    Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
    newScript.appendChild(document.createTextNode(content))
    item.parentNode.replaceChild(newScript, item)
  })

  GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()

  typeof chatBtnFn === 'function' && chatBtnFn()
  typeof panguInit === 'function' && panguInit()

  // google analytics
  typeof gtag === 'function' && gtag('config', '', {'page_path': window.location.pathname});

  // baidu analytics
  typeof _hmt === 'object' && _hmt.push(['_trackPageview',window.location.pathname]);

  typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()

  // prismjs
  typeof Prism === 'object' && Prism.highlightAll()

  typeof preloader === 'object' && preloader.endLoading()
})

document.addEventListener('pjax:error', (e) => {
  if (e.request.status === 404) {
    pjax.loadUrl('/404.html')
  }
})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><!-- hexo injector body_end start --> <script data-pjax>if(document.getElementById('recent-posts') && (location.pathname ==='/'|| '/' ==='all')){
    var parent = document.getElementById('recent-posts');
    var child = '<div class="recent-post-item" style="width:100%;height: auto"><div id="catalog_magnet"><div class="magnet_item"><a class="magnet_link" href="https://www.naste.top:1024/categories/Java/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">🍡 XiaoFeiのJava学习笔记 (55)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><div class="magnet_item"><a class="magnet_link" href="https://www.naste.top:1024/categories/Linux/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">🍼 XiaoFeiのLinux笔记 (33)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><div class="magnet_item"><a class="magnet_link" href="https://www.naste.top:1024/categories/Python/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">🍉 XiaoFeiのPython笔记 (2)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><div class="magnet_item"><a class="magnet_link" href="https://www.naste.top:1024/categories/前端/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">🍟 XiaoFeiの前端笔记 (17)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><div class="magnet_item"><a class="magnet_link" href="https://www.naste.top:1024/categories/Other/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">🍥 XiaoFeiのOther笔记 (10)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><div class="magnet_item" style="visibility: hidden"></div><a class="magnet_link_more"  href="https://www.naste.top:1024/categories/" style="flex:1;text-align: center;margin-bottom: 10px;">查看更多...</a></div></div>';
    console.log('已挂载magnet')
    parent.insertAdjacentHTML("afterbegin",child)}
     </script><style>#catalog_magnet{flex-wrap: wrap;display: flex;width:100%;justify-content:space-between;padding: 10px 10px 0 10px;align-content: flex-start;}.magnet_item{flex-basis: calc(33.333333333333336% - 5px);background: #e9e9e9;margin-bottom: 10px;border-radius: 8px;transition: all 0.2s ease-in-out;}.magnet_item:hover{background: var(--text-bg-hover)}.magnet_link_more{color:#555}.magnet_link{color:black}.magnet_link:hover{color:white}@media screen and (max-width: 600px) {.magnet_item {flex-basis: 100%;}}.magnet_link_context{display:flex;padding: 10px;font-size:16px;transition: all 0.2s ease-in-out;}.magnet_link_context:hover{padding: 10px 20px;}</style>
    <style></style><script data-pjax>
  function butterfly_swiper_injector_config(){
    var parent_div_git = document.getElementById('recent-posts');
    var item_html = '<div class="recent-post-item" style="height: auto;width: 100%"><div class="blog-slider swiper-container-fade swiper-container-horizontal" id="swiper_container"><div class="blog-slider__wrp swiper-wrapper" style="transition-duration: 0ms;"><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;posts/204253054.html&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="https://www.naste.top:9000/webp/1675912191.webp" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-03-08</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;posts/204253054.html&quot;);" href="javascript:void(0);" alt="">SpringBoot使用实现定时任务和xxl-job实现分布式任务调度</a><div class="blog-slider__text">SpringBoot使用实现定时任务和xxl-job实现分布式任务调度</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;posts/204253054.html&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;posts/538133837.html&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="https://www.naste.top:9000/webp/1678672933.webp" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-03-15</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;posts/538133837.html&quot;);" href="javascript:void(0);" alt="">Hexo中Markdown语法与外挂标签写法汇总</a><div class="blog-slider__text">Hexo中Markdown语法与外挂标签写法汇总</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;posts/538133837.html&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div></div><div class="blog-slider__pagination swiper-pagination-clickable swiper-pagination-bullets"></div></div></div>';
    console.log('已挂载butterfly_swiper')
    parent_div_git.insertAdjacentHTML("afterbegin",item_html)
    }
  var elist = 'undefined'.split(',');
  var cpage = location.pathname;
  var epage = '/';
  var flag = 0;

  for (var i=0;i<elist.length;i++){
    if (cpage.includes(elist[i])){
      flag++;
    }
  }

  if ((epage ==='all')&&(flag == 0)){
    butterfly_swiper_injector_config();
  }
  else if (epage === cpage){
    butterfly_swiper_injector_config();
  }
  </script><script defer src="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js"></script><script defer data-pjax src="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper_init.js"></script><div class="js-pjax"><script async="async">var arr = document.getElementsByClassName('recent-post-item');
for(var i = 0;i<arr.length;i++){
    arr[i].classList.add('wow');
    arr[i].classList.add('animate__zoomIn');
    arr[i].setAttribute('data-wow-duration', '2s');
    arr[i].setAttribute('data-wow-delay', '200ms');
    arr[i].setAttribute('data-wow-offset', '30');
    arr[i].setAttribute('data-wow-iteration', '1');
  }</script><script async="async">var arr = document.getElementsByClassName('card-widget');
for(var i = 0;i<arr.length;i++){
    arr[i].classList.add('wow');
    arr[i].classList.add('animate__zoomIn');
    arr[i].setAttribute('data-wow-duration', '2s');
    arr[i].setAttribute('data-wow-delay', '200ms');
    arr[i].setAttribute('data-wow-offset', '30');
    arr[i].setAttribute('data-wow-iteration', '1');
  }</script></div><script defer src="https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow.min.js"></script><script defer src="https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow_init.js"></script><script data-pjax src="https://npm.elemecdn.com/hexo-filter-gitcalendar/lib/gitcalendar.js"></script><script data-pjax>
  function gitcalendar_injector_config(){
      var parent_div_git = document.getElementById('gitZone');
      var item_html = '<div class="recent-post-item" id="gitcalendarBar" style="width:100%;height:auto;padding:10px;"><style>#git_container{min-height: 320px}@media screen and (max-width:650px) {#git_container{min-height: 0px}}</style><div id="git_loading" style="width:10%;height:100%;margin:0 auto;display: block;"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50" xml:space="preserve"><path fill="#d0d0d0" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" transform="rotate(275.098 25 25)"><animatetransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animatetransform></path></svg><style>#git_container{display: none;}</style></div><div id="git_container"></div></div>';
      parent_div_git.insertAdjacentHTML("afterbegin",item_html)
      console.log('已挂载gitcalendar')
      }

    if( document.getElementById('gitZone') && (location.pathname ==='/personal/about/'|| '/personal/about/' ==='all')){
        gitcalendar_injector_config()
        GitCalendarInit("https://gitcalendar.naste.top/api?xiao-i-fei",['#d9e0df', '#c6e0dc', '#a8dcd4', '#9adcd2', '#89ded1', '#77e0d0', '#5fdecb', '#47dcc6', '#39dcc3', '#1fdabe', '#00dab9'],'xiao-i-fei')
    }
  </script><!-- hexo injector body_end end --></body></html>